<!-- build time:Tue Feb 18 2020 17:19:27 GMT+0800 (China Standard Time) --><!DOCTYPE html><html lang="zh"><head><meta charset="utf-8"><meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1"><meta name="viewport" content="width=device-width,initial-scale=1,maximum-scale=1,minimum-scale=1,user-scalable=no,minimal-ui"><meta name="renderer" content="webkit"><meta http-equiv="Cache-Control" content="no-transform"><meta http-equiv="Cache-Control" content="no-siteapp"><meta name="apple-mobile-web-app-capable" content="yes"><meta name="apple-mobile-web-app-status-bar-style" content="black"><meta name="format-detection" content="telephone=no,email=no,adress=no"><meta name="theme-color" content="#000000"><meta http-equiv="window-target" content="_top"><title>Spring Boot MyBatis 入门 | calm&#39;s blog</title><meta name="description" content="摘要: 原创出处 http:&#x2F;&#x2F;www.iocoder.cn&#x2F;Spring-Boot&#x2F;MyBatis&#x2F; 「芋道源码」，卡姆在此基础上略作修改，欢迎转载，保留摘要，谢谢！1. 概述在 DAL 数据访问层，目前会有三种方向的解决方案：JDBCMyBatisJPA「芋道源码」在 知识星球 中，做过一个简单的调研，看看大家使用哪个为主。结果是 MyBatis &gt; JPA &gt; JDBC 。这个也"><meta property="og:type" content="article"><meta property="og:title" content="Spring Boot MyBatis 入门"><meta property="og:url" content="https://calm_java.gitee.io/blog/2020/01/08/labs-springboot2-mybatis/index.html"><meta property="og:site_name" content="卡姆"><meta property="og:description" content="摘要: 原创出处 http:&#x2F;&#x2F;www.iocoder.cn&#x2F;Spring-Boot&#x2F;MyBatis&#x2F; 「芋道源码」，卡姆在此基础上略作修改，欢迎转载，保留摘要，谢谢！1. 概述在 DAL 数据访问层，目前会有三种方向的解决方案：JDBCMyBatisJPA「芋道源码」在 知识星球 中，做过一个简单的调研，看看大家使用哪个为主。结果是 MyBatis &gt; JPA &gt; JDBC 。这个也"><meta property="og:locale" content="zh_CN"><meta property="article:published_time" content="2020-01-08T05:57:04.000Z"><meta property="article:modified_time" content="2020-01-08T09:58:10.848Z"><meta property="article:author" content="calm"><meta property="article:tag" content="MyBatis"><meta name="twitter:card" content="summary"><link rel="canonical" href="https://calm_java.gitee.io/blog/2020/01/08/labs-springboot2-mybatis/index.html"><link rel="alternate" href="/atom.xml" title="卡姆" type="application/atom+xml"><link rel="icon" href="/blog/images/avatar.jpg" type="image/x-icon"><link rel="stylesheet" href="/blog/css/style.css"><link rel="stylesheet" href="//cdn.jsdelivr.net/npm/gitalk@1.4.0/dist/gitalk.min.css"><meta name="generator" content="Hexo 4.2.0"></head><body class="main-center theme-green" itemscope itemtype="http://schema.org/WebPage"><header class="header" itemscope itemtype="http://schema.org/WPHeader"><div class="slimContent"><div class="navbar-header"><div class="profile-block text-center"><a id="avatar" href="https://github.com/yuyong725" target="_blank"><img class="img-circle img-rotate" src="/blog/images/avatar.jpg" width="200" height="200"></a><h2 id="name" class="hidden-xs hidden-sm">卡姆</h2><h3 id="title" class="hidden-xs hidden-sm hidden-md">a Java coder need calm</h3><small id="location" class="text-muted hidden-xs hidden-sm"><i class="icon icon-map-marker"></i> hangzhou, China</small></div><div class="search" id="search-form-wrap"><form class="search-form sidebar-form"><div class="input-group"><input type="text" class="search-form-input form-control" placeholder="搜索"> <span class="input-group-btn"><button type="submit" class="search-form-submit btn btn-flat" onclick="return!1"><i class="icon icon-search"></i></button></span></div></form><div class="ins-search"><div class="ins-search-mask"></div><div class="ins-search-container"><div class="ins-input-wrapper"><input type="text" class="ins-search-input" placeholder="想要查找什么..." x-webkit-speech> <button type="button" class="close ins-close ins-selectable" data-dismiss="modal" aria-label="Close"><span aria-hidden="true">×</span></button></div><div class="ins-section-wrapper"><div class="ins-section-container"></div></div></div></div></div><button class="navbar-toggle collapsed" type="button" data-toggle="collapse" data-target="#main-navbar" aria-controls="main-navbar" aria-expanded="false"><span class="sr-only">Toggle navigation</span> <span class="icon-bar"></span> <span class="icon-bar"></span> <span class="icon-bar"></span></button></div><nav id="main-navbar" class="collapse navbar-collapse" itemscope itemtype="http://schema.org/SiteNavigationElement" role="navigation"><ul class="nav navbar-nav main-nav"><li class="menu-item menu-item-home"><a href="/blog/."><i class="icon icon-home-fill"></i> <span class="menu-title">首页</span></a></li><li class="menu-item menu-item-archives"><a href="/blog/archives"><i class="icon icon-archives-fill"></i> <span class="menu-title">归档</span></a></li><li class="menu-item menu-item-categories"><a href="/blog/categories"><i class="icon icon-folder"></i> <span class="menu-title">分类</span></a></li><li class="menu-item menu-item-tags"><a href="/blog/tags"><i class="icon icon-tags"></i> <span class="menu-title">标签</span></a></li><li class="menu-item menu-item-repository"><a href="/blog/repository"><i class="icon icon-project"></i> <span class="menu-title">项目</span></a></li><li class="menu-item menu-item-books"><a href="/blog/books"><i class="icon icon-book-fill"></i> <span class="menu-title">书单</span></a></li><li class="menu-item menu-item-links"><a href="/blog/links"><i class="icon icon-friendship"></i> <span class="menu-title">友链</span></a></li><li class="menu-item menu-item-about"><a href="/blog/about"><i class="icon icon-cup-fill"></i> <span class="menu-title">关于</span></a></li></ul><ul class="social-links"><li><a href="https://github.com/yuyong725" target="_blank" title="Github" data-toggle="tooltip" data-placement="top"><i class="icon icon-github"></i></a></li></ul></nav></div></header><aside class="sidebar" itemscope itemtype="http://schema.org/WPSideBar"><div class="slimContent"><div class="widget"><h3 class="widget-title">公告</h3><div class="widget-body"><div id="board"><div class="content"><p>欢迎交流与分享经验!</p></div></div></div></div><div class="widget"><h3 class="widget-title">分类</h3><div class="widget-body"><ul class="category-list"><li class="category-list-item"><a class="category-list-link" href="/blog/categories/CI-DI/">CI/DI</a><span class="category-list-count">1</span></li><li class="category-list-item"><a class="category-list-link" href="/blog/categories/git/">git</a><span class="category-list-count">1</span></li><li class="category-list-item"><a class="category-list-link" href="/blog/categories/labs/">labs</a><span class="category-list-count">14</span></li></ul></div></div><div class="widget"><h3 class="widget-title">标签</h3><div class="widget-body"><ul class="tag-list" itemprop="keywords"><li class="tag-list-item"><a class="tag-list-link" href="/blog/tags/MyBatis/" rel="tag">MyBatis</a><span class="tag-list-count">1</span></li><li class="tag-list-item"><a class="tag-list-link" href="/blog/tags/Oauth2/" rel="tag">Oauth2</a><span class="tag-list-count">1</span></li><li class="tag-list-item"><a class="tag-list-link" href="/blog/tags/Spring-Security/" rel="tag">Spring Security</a><span class="tag-list-count">1</span></li><li class="tag-list-item"><a class="tag-list-link" href="/blog/tags/SpringMVC/" rel="tag">SpringMVC</a><span class="tag-list-count">1</span></li><li class="tag-list-item"><a class="tag-list-link" href="/blog/tags/docker/" rel="tag">docker</a><span class="tag-list-count">1</span></li><li class="tag-list-item"><a class="tag-list-link" href="/blog/tags/dubbo/" rel="tag">dubbo</a><span class="tag-list-count">1</span></li><li class="tag-list-item"><a class="tag-list-link" href="/blog/tags/git/" rel="tag">git</a><span class="tag-list-count">1</span></li><li class="tag-list-item"><a class="tag-list-link" href="/blog/tags/jdbctemplate/" rel="tag">jdbctemplate</a><span class="tag-list-count">1</span></li><li class="tag-list-item"><a class="tag-list-link" href="/blog/tags/jerkins/" rel="tag">jerkins</a><span class="tag-list-count">1</span></li><li class="tag-list-item"><a class="tag-list-link" href="/blog/tags/job/" rel="tag">job</a><span class="tag-list-count">2</span></li><li class="tag-list-item"><a class="tag-list-link" href="/blog/tags/jpa/" rel="tag">jpa</a><span class="tag-list-count">1</span></li><li class="tag-list-item"><a class="tag-list-link" href="/blog/tags/pdf/" rel="tag">pdf</a><span class="tag-list-count">1</span></li><li class="tag-list-item"><a class="tag-list-link" href="/blog/tags/redis/" rel="tag">redis</a><span class="tag-list-count">1</span></li><li class="tag-list-item"><a class="tag-list-link" href="/blog/tags/%E5%88%86%E5%BA%93%E5%88%86%E8%A1%A8/" rel="tag">分库分表</a><span class="tag-list-count">1</span></li><li class="tag-list-item"><a class="tag-list-link" href="/blog/tags/%E5%A4%9A%E6%95%B0%E6%8D%AE%E6%BA%90/" rel="tag">多数据源</a><span class="tag-list-count">1</span></li><li class="tag-list-item"><a class="tag-list-link" href="/blog/tags/%E6%95%B0%E6%8D%AE%E5%BA%93%E7%89%88%E6%9C%AC%E7%AE%A1%E7%90%86/" rel="tag">数据库版本管理</a><span class="tag-list-count">1</span></li><li class="tag-list-item"><a class="tag-list-link" href="/blog/tags/%E6%95%B0%E6%8D%AE%E5%BA%93%E8%BF%9E%E6%8E%A5%E6%B1%A0/" rel="tag">数据库连接池</a><span class="tag-list-count">1</span></li><li class="tag-list-item"><a class="tag-list-link" href="/blog/tags/%E7%BC%93%E5%AD%98/" rel="tag">缓存</a><span class="tag-list-count">2</span></li></ul></div></div><div class="widget"><h3 class="widget-title">标签云</h3><div class="widget-body tagcloud"><a href="/blog/tags/MyBatis/" style="font-size:13px">MyBatis</a> <a href="/blog/tags/Oauth2/" style="font-size:13px">Oauth2</a> <a href="/blog/tags/Spring-Security/" style="font-size:13px">Spring Security</a> <a href="/blog/tags/SpringMVC/" style="font-size:13px">SpringMVC</a> <a href="/blog/tags/docker/" style="font-size:13px">docker</a> <a href="/blog/tags/dubbo/" style="font-size:13px">dubbo</a> <a href="/blog/tags/git/" style="font-size:13px">git</a> <a href="/blog/tags/jdbctemplate/" style="font-size:13px">jdbctemplate</a> <a href="/blog/tags/jerkins/" style="font-size:13px">jerkins</a> <a href="/blog/tags/job/" style="font-size:14px">job</a> <a href="/blog/tags/jpa/" style="font-size:13px">jpa</a> <a href="/blog/tags/pdf/" style="font-size:13px">pdf</a> <a href="/blog/tags/redis/" style="font-size:13px">redis</a> <a href="/blog/tags/%E5%88%86%E5%BA%93%E5%88%86%E8%A1%A8/" style="font-size:13px">分库分表</a> <a href="/blog/tags/%E5%A4%9A%E6%95%B0%E6%8D%AE%E6%BA%90/" style="font-size:13px">多数据源</a> <a href="/blog/tags/%E6%95%B0%E6%8D%AE%E5%BA%93%E7%89%88%E6%9C%AC%E7%AE%A1%E7%90%86/" style="font-size:13px">数据库版本管理</a> <a href="/blog/tags/%E6%95%B0%E6%8D%AE%E5%BA%93%E8%BF%9E%E6%8E%A5%E6%B1%A0/" style="font-size:13px">数据库连接池</a> <a href="/blog/tags/%E7%BC%93%E5%AD%98/" style="font-size:14px">缓存</a></div></div><div class="widget"><h3 class="widget-title">归档</h3><div class="widget-body"><ul class="archive-list"><li class="archive-list-item"><a class="archive-list-link" href="/blog/archives/2020/02/">二月 2020</a><span class="archive-list-count">5</span></li><li class="archive-list-item"><a class="archive-list-link" href="/blog/archives/2020/01/">一月 2020</a><span class="archive-list-count">8</span></li><li class="archive-list-item"><a class="archive-list-link" href="/blog/archives/2019/12/">十二月 2019</a><span class="archive-list-count">4</span></li></ul></div></div><div class="widget"><h3 class="widget-title">最新文章</h3><div class="widget-body"><ul class="recent-post-list list-unstyled no-thumbnail"><li><div class="item-inner"><p class="item-category"><a class="category-link" href="/blog/categories/labs/">labs</a></p><p class="item-title"><a href="/blog/2020/02/18/labs-springboot2-async-Job/" class="title">Spring Boot 异步任务入门</a></p><p class="item-date"><time datetime="2020-02-18T05:10:39.000Z" itemprop="datePublished">2020-02-18</time></p></div></li><li><div class="item-inner"><p class="item-category"><a class="category-link" href="/blog/categories/labs/">labs</a></p><p class="item-title"><a href="/blog/2020/02/18/labs-springboot2-job/" class="title">Spring Boot 定时任务入门</a></p><p class="item-date"><time datetime="2020-02-18T02:26:31.000Z" itemprop="datePublished">2020-02-18</time></p></div></li><li><div class="item-inner"><p class="item-category"><a class="category-link" href="/blog/categories/labs/">labs</a></p><p class="item-title"><a href="/blog/2020/02/17/labs-springboot2-database-version-control/" class="title">Spring Boot 数据库版本管理入门</a></p><p class="item-date"><time datetime="2020-02-17T12:05:54.000Z" itemprop="datePublished">2020-02-17</time></p></div></li><li><div class="item-inner"><p class="item-category"><a class="category-link" href="/blog/categories/labs/">labs</a></p><p class="item-title"><a href="/blog/2020/02/17/labs-springboot2-sharding-datasource/" class="title">Spring Boot 分库分表入门</a></p><p class="item-date"><time datetime="2020-02-17T08:15:31.000Z" itemprop="datePublished">2020-02-17</time></p></div></li><li><div class="item-inner"><p class="item-category"><a class="category-link" href="/blog/categories/labs/">labs</a></p><p class="item-title"><a href="/blog/2020/02/13/labs-springboot2-dynamic-datasource/" class="title">Spring Boot 多数据源（读写分离）入门</a></p><p class="item-date"><time datetime="2020-02-13T03:18:37.000Z" itemprop="datePublished">2020-02-13</time></p></div></li></ul></div></div></div></aside><aside class="sidebar sidebar-toc collapse in" id="collapseToc" itemscope itemtype="http://schema.org/WPSideBar"><div class="slimContent"><nav id="toc" class="article-toc"><h3 class="toc-title">文章目录</h3><ol class="toc"><li class="toc-item toc-level-1"><a class="toc-link" href="#1-概述"><span class="toc-text">1. 概述</span></a></li><li class="toc-item toc-level-1"><a class="toc-link" href="#2-MyBatis-XML"><span class="toc-text">2. MyBatis + XML</span></a><ol class="toc-child"><li class="toc-item toc-level-2"><a class="toc-link" href="#2-1-引入依赖"><span class="toc-text">2.1 引入依赖</span></a></li><li class="toc-item toc-level-2"><a class="toc-link" href="#2-2-MyBatisXmlApplication"><span class="toc-text">2.2 MyBatisXmlApplication</span></a></li><li class="toc-item toc-level-2"><a class="toc-link" href="#2-3-应用配置文件"><span class="toc-text">2.3 应用配置文件</span></a></li><li class="toc-item toc-level-2"><a class="toc-link" href="#2-4-MyBatis-配置文件"><span class="toc-text">2.4 MyBatis 配置文件</span></a></li><li class="toc-item toc-level-2"><a class="toc-link" href="#2-5-UserDO"><span class="toc-text">2.5 UserDO</span></a></li><li class="toc-item toc-level-2"><a class="toc-link" href="#2-6-UserMapper"><span class="toc-text">2.6 UserMapper</span></a></li><li class="toc-item toc-level-2"><a class="toc-link" href="#2-7-简单测试"><span class="toc-text">2.7 简单测试</span></a></li></ol></li><li class="toc-item toc-level-1"><a class="toc-link" href="#3-MyBatis-注解"><span class="toc-text">3. MyBatis + 注解</span></a><ol class="toc-child"><li class="toc-item toc-level-2"><a class="toc-link" href="#3-1-差异部分"><span class="toc-text">3.1 差异部分</span></a></li><li class="toc-item toc-level-2"><a class="toc-link" href="#3-2-UserMapper"><span class="toc-text">3.2 UserMapper</span></a></li><li class="toc-item toc-level-2"><a class="toc-link" href="#3-3-简单测试"><span class="toc-text">3.3 简单测试</span></a></li></ol></li><li class="toc-item toc-level-1"><a class="toc-link" href="#4-MyBatis-Plus"><span class="toc-text">4. MyBatis-Plus</span></a><ol class="toc-child"><li class="toc-item toc-level-2"><a class="toc-link" href="#4-1-引入依赖"><span class="toc-text">4.1 引入依赖</span></a></li><li class="toc-item toc-level-2"><a class="toc-link" href="#4-2-MyBatisPlusApplication"><span class="toc-text">4.2 MyBatisPlusApplication</span></a></li><li class="toc-item toc-level-2"><a class="toc-link" href="#4-3-应用配置文件"><span class="toc-text">4.3 应用配置文件</span></a></li><li class="toc-item toc-level-2"><a class="toc-link" href="#4-4-UserDO"><span class="toc-text">4.4 UserDO</span></a></li><li class="toc-item toc-level-2"><a class="toc-link" href="#4-5-UserMapper"><span class="toc-text">4.5 UserMapper</span></a></li><li class="toc-item toc-level-2"><a class="toc-link" href="#4-6-简单测试"><span class="toc-text">4.6 简单测试</span></a></li></ol></li><li class="toc-item toc-level-1"><a class="toc-link" href="#5-tkmybatis"><span class="toc-text">5. tkmybatis</span></a><ol class="toc-child"><li class="toc-item toc-level-2"><a class="toc-link" href="#5-1-引入依赖"><span class="toc-text">5.1 引入依赖</span></a></li><li class="toc-item toc-level-2"><a class="toc-link" href="#5-2-MyBatisTkApplication"><span class="toc-text">5.2 MyBatisTkApplication</span></a></li><li class="toc-item toc-level-2"><a class="toc-link" href="#5-3-应用配置文件"><span class="toc-text">5.3 应用配置文件</span></a></li><li class="toc-item toc-level-2"><a class="toc-link" href="#5-4-MyBatis-配置文件"><span class="toc-text">5.4 MyBatis 配置文件</span></a></li><li class="toc-item toc-level-2"><a class="toc-link" href="#5-5-UserDO"><span class="toc-text">5.5 UserDO</span></a></li><li class="toc-item toc-level-2"><a class="toc-link" href="#5-6-UserMapper"><span class="toc-text">5.6 UserMapper</span></a></li><li class="toc-item toc-level-2"><a class="toc-link" href="#5-7-简单测试"><span class="toc-text">5.7 简单测试</span></a></li><li class="toc-item toc-level-2"><a class="toc-link" href="#5-8-自定义扩展"><span class="toc-text">5.8 自定义扩展</span></a><ol class="toc-child"><li class="toc-item toc-level-3"><a class="toc-link" href="#5-8-1-自定义逻辑删除通用mapper"><span class="toc-text">5.8.1 自定义逻辑删除通用mapper</span></a></li></ol></li></ol></li><li class="toc-item toc-level-1"><a class="toc-link" href="#666-彩蛋"><span class="toc-text">666. 彩蛋</span></a></li></ol></nav></div></aside><main class="main" role="main"><div class="content"><article id="post-labs-springboot2-mybatis" class="article article-type-post" itemscope itemtype="http://schema.org/BlogPosting"><div class="article-header"><h1 class="article-title" itemprop="name">Spring Boot MyBatis 入门</h1><div class="article-meta"><span class="article-date"><i class="icon icon-calendar-check"></i> <a href="/blog/2020/01/08/labs-springboot2-mybatis/" class="article-date"><time datetime="2020-01-08T05:57:04.000Z" itemprop="datePublished">2020-01-08</time></a></span> <span class="article-category"><i class="icon icon-folder"></i> <a class="article-category-link" href="/blog/categories/labs/">labs</a></span> <span class="article-tag"><i class="icon icon-tags"></i> <a class="article-tag-link" href="/blog/tags/MyBatis/" rel="tag">MyBatis</a></span> <span class="article-read hidden-xs"><i class="icon icon-eye-fill" aria-hidden="true"></i> <span id="busuanzi_container_page_pv"><span id="busuanzi_value_page_pv">0</span></span></span> <span class="post-comment"><i class="icon icon-comment"></i> <a href="/blog/2020/01/08/labs-springboot2-mybatis/#comments" class="article-comment-link">评论</a></span> <span class="post-wordcount hidden-xs" itemprop="wordCount">字数统计: 8.1k(字)</span> <span class="post-readcount hidden-xs" itemprop="timeRequired">阅读时长: 38(分)</span></div></div><div class="article-entry marked-body" itemprop="articleBody"><blockquote><p>摘要: 原创出处 <a href="http://www.iocoder.cn/Spring-Boot/MyBatis/" target="_blank" rel="noopener">http://www.iocoder.cn/Spring-Boot/MyBatis/</a> 「芋道源码」，卡姆在此基础上略作修改，欢迎转载，保留摘要，谢谢！</p></blockquote><h1 id="1-概述"><a href="#1-概述" class="headerlink" title="1. 概述"></a>1. 概述</h1><p>在 DAL 数据访问层，目前会有三种方向的解决方案：</p><ul><li>JDBC</li><li>MyBatis</li><li><a href="https://zh.wikipedia.org/wiki/Java持久化API" target="_blank" rel="noopener">JPA</a></li></ul><p>「芋道源码」在 <a href="http://www.iocoder.cn/zhishixingqiu/?self" target="_blank" rel="noopener">知识星球</a> 中，做过一个简单的调研，看看大家使用哪个为主。结果是 MyBatis &gt; JPA &gt; JDBC 。这个也符合在知乎上看到的两篇文章：</p><ul><li><a href="https://www.zhihu.com/question/50729231" target="_blank" rel="noopener">《MyBatis 为什么在国内相当流行?》</a></li><li><a href="https://www.zhihu.com/question/22098131" target="_blank" rel="noopener">《为什么阿里巴巴的持久层采用 iBatis 框架,而不使用 hibernate 框架呢？感觉 hibernate 更厉害的样子？》</a></li></ul><blockquote><p>注意，几种方式可以组合使用。</p></blockquote><ul><li>MyBatis + <a href="https://mybatis.org/mybatis-3/zh/sqlmap-xml.html" target="_blank" rel="noopener">XML</a></li><li>MyBatis + <a href="https://blog.csdn.net/myNameIssls/article/details/21610249" target="_blank" rel="noopener">注解</a></li><li><a href="https://mp.baomidou.com/" target="_blank" rel="noopener">MyBatis-Plus</a></li><li><a href="http://www.mybatis.tk/" target="_blank" rel="noopener">tkmybatis</a></li></ul><p>卡姆个人比较喜欢 tkmybatis，因为它封装了单表的增删改查，提供了sqlHelper工具类用于自定义provider扩展，没有 MyBatis-Plus 侵入的那么深。</p><p>下面，我们上面列的四种方式，逐个来入门。</p><h1 id="2-MyBatis-XML"><a href="#2-MyBatis-XML" class="headerlink" title="2. MyBatis + XML"></a>2. MyBatis + XML</h1><blockquote><p>示例代码对应仓库：<a href="https://github.com/yuyong725/labs-springboot2/tree/master/labs-springboot2-data-access/labs-springboot2-mybatis/labs-springboot2-mybatis-xml" target="_blank" rel="noopener">labs-springboot2-mybatis-xml</a> 。</p></blockquote><p>本小节，我们会使用 <a href="https://github.com/mybatis/spring-boot-starter" target="_blank" rel="noopener">mybatis-spring-boot-starter</a> 自动化配置 MyBatis 主要配置。同时，在 XML 中编写相应的 SQL 操作。</p><h2 id="2-1-引入依赖"><a href="#2-1-引入依赖" class="headerlink" title="2.1 引入依赖"></a>2.1 引入依赖</h2><p>在 <code>pom.xml</code> 文件中，引入相关依赖。</p><figure class="highlight xml"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">&lt;?xml version="1.0" encoding="UTF-8"?&gt;</span></span><br><span class="line"><span class="tag">&lt;<span class="name">project</span> <span class="attr">xmlns</span>=<span class="string">"http://maven.apache.org/POM/4.0.0"</span></span></span><br><span class="line"><span class="tag">         <span class="attr">xmlns:xsi</span>=<span class="string">"http://www.w3.org/2001/XMLSchema-instance"</span></span></span><br><span class="line"><span class="tag">         <span class="attr">xsi:schemaLocation</span>=<span class="string">"http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"</span>&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">parent</span>&gt;</span></span><br><span class="line">        <span class="tag">&lt;<span class="name">artifactId</span>&gt;</span>labs-springboot2-mybatis<span class="tag">&lt;/<span class="name">artifactId</span>&gt;</span></span><br><span class="line">        <span class="tag">&lt;<span class="name">groupId</span>&gt;</span>cn.javadog<span class="tag">&lt;/<span class="name">groupId</span>&gt;</span></span><br><span class="line">        <span class="tag">&lt;<span class="name">version</span>&gt;</span>1.0-SNAPSHOT<span class="tag">&lt;/<span class="name">version</span>&gt;</span></span><br><span class="line">    <span class="tag">&lt;/<span class="name">parent</span>&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">modelVersion</span>&gt;</span>4.0.0<span class="tag">&lt;/<span class="name">modelVersion</span>&gt;</span></span><br><span class="line"></span><br><span class="line">    <span class="tag">&lt;<span class="name">artifactId</span>&gt;</span>labs-springboot2-mybatis-xml<span class="tag">&lt;/<span class="name">artifactId</span>&gt;</span></span><br><span class="line"></span><br><span class="line">    <span class="tag">&lt;<span class="name">dependencies</span>&gt;</span></span><br><span class="line">        <span class="comment">&lt;!-- 实现对数据库连接池的自动化配置 --&gt;</span></span><br><span class="line">        <span class="tag">&lt;<span class="name">dependency</span>&gt;</span></span><br><span class="line">            <span class="tag">&lt;<span class="name">groupId</span>&gt;</span>org.springframework.boot<span class="tag">&lt;/<span class="name">groupId</span>&gt;</span></span><br><span class="line">            <span class="tag">&lt;<span class="name">artifactId</span>&gt;</span>spring-boot-starter-jdbc<span class="tag">&lt;/<span class="name">artifactId</span>&gt;</span></span><br><span class="line">        <span class="tag">&lt;/<span class="name">dependency</span>&gt;</span></span><br><span class="line">        <span class="comment">&lt;!-- 本示例，我们使用 MySQL --&gt;</span></span><br><span class="line">        <span class="tag">&lt;<span class="name">dependency</span>&gt;</span></span><br><span class="line">            <span class="tag">&lt;<span class="name">groupId</span>&gt;</span>mysql<span class="tag">&lt;/<span class="name">groupId</span>&gt;</span></span><br><span class="line">            <span class="tag">&lt;<span class="name">artifactId</span>&gt;</span>mysql-connector-java<span class="tag">&lt;/<span class="name">artifactId</span>&gt;</span></span><br><span class="line">        <span class="tag">&lt;/<span class="name">dependency</span>&gt;</span></span><br><span class="line"></span><br><span class="line">        <span class="comment">&lt;!-- 实现对 MyBatis 的自动化配置 --&gt;</span></span><br><span class="line">        <span class="tag">&lt;<span class="name">dependency</span>&gt;</span></span><br><span class="line">            <span class="tag">&lt;<span class="name">groupId</span>&gt;</span>org.mybatis.spring.boot<span class="tag">&lt;/<span class="name">groupId</span>&gt;</span></span><br><span class="line">            <span class="tag">&lt;<span class="name">artifactId</span>&gt;</span>mybatis-spring-boot-starter<span class="tag">&lt;/<span class="name">artifactId</span>&gt;</span></span><br><span class="line">        <span class="tag">&lt;/<span class="name">dependency</span>&gt;</span></span><br><span class="line"></span><br><span class="line">        <span class="comment">&lt;!-- 方便等会写单元测试 --&gt;</span></span><br><span class="line">        <span class="tag">&lt;<span class="name">dependency</span>&gt;</span></span><br><span class="line">            <span class="tag">&lt;<span class="name">groupId</span>&gt;</span>org.springframework.boot<span class="tag">&lt;/<span class="name">groupId</span>&gt;</span></span><br><span class="line">            <span class="tag">&lt;<span class="name">artifactId</span>&gt;</span>spring-boot-starter-test<span class="tag">&lt;/<span class="name">artifactId</span>&gt;</span></span><br><span class="line">            <span class="tag">&lt;<span class="name">scope</span>&gt;</span>test<span class="tag">&lt;/<span class="name">scope</span>&gt;</span></span><br><span class="line">        <span class="tag">&lt;/<span class="name">dependency</span>&gt;</span></span><br><span class="line"></span><br><span class="line">        <span class="tag">&lt;<span class="name">dependency</span>&gt;</span></span><br><span class="line">            <span class="tag">&lt;<span class="name">groupId</span>&gt;</span>org.projectlombok<span class="tag">&lt;/<span class="name">groupId</span>&gt;</span></span><br><span class="line">            <span class="tag">&lt;<span class="name">artifactId</span>&gt;</span>lombok<span class="tag">&lt;/<span class="name">artifactId</span>&gt;</span></span><br><span class="line">        <span class="tag">&lt;/<span class="name">dependency</span>&gt;</span></span><br><span class="line">    <span class="tag">&lt;/<span class="name">dependencies</span>&gt;</span></span><br><span class="line"><span class="tag">&lt;/<span class="name">project</span>&gt;</span></span><br></pre></td></tr></table></figure><p>具体每个依赖的作用，胖友自己认真看下添加的所有注释噢。</p><h2 id="2-2-MyBatisXmlApplication"><a href="#2-2-MyBatisXmlApplication" class="headerlink" title="2.2 MyBatisXmlApplication"></a>2.2 MyBatisXmlApplication</h2><p>创建 <code>MyBatisXmlApplication</code> 类，配置 <code>@MapperScan</code> 注解，扫描对应 Mapper 接口所在的包路径。代码如下：</p><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">// MyBatisXmlApplication.java</span></span><br><span class="line"></span><br><span class="line"><span class="meta">@SpringBootApplication</span></span><br><span class="line"><span class="meta">@MapperScan</span>(basePackages = <span class="string">"cn.javadog.labs.springboot2.mybatis.xml.mapper"</span>)</span><br><span class="line"><span class="keyword">public</span> <span class="class"><span class="keyword">class</span> <span class="title">MyBatisXmlApplication</span> </span>&#123;</span><br><span class="line"></span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><ul><li><code>cn.javadog.labs.springboot2.mybatis.xml.mapper</code> 包路径下，就是我们 Mapper 接口所在的包路径。</li><li>建议1 ：因为这里是做示例。实际项目中，可以考虑创建一个 MyBatisConfig 配置类，将 <code>@MapperScan</code> 注解添加到其上。</li></ul><h2 id="2-3-应用配置文件"><a href="#2-3-应用配置文件" class="headerlink" title="2.3 应用配置文件"></a>2.3 应用配置文件</h2><p>在 <code>resources</code>目录下，创建 <code>application.yaml</code> 配置文件。配置如下：</p><figure class="highlight yaml"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br></pre></td><td class="code"><pre><span class="line"><span class="attr">spring:</span></span><br><span class="line">  <span class="comment"># datasource 数据源配置内容</span></span><br><span class="line">  <span class="attr">datasource:</span></span><br><span class="line">    <span class="attr">url:</span> <span class="string">jdbc:mysql://127.0.0.1:3306/labs-springboot2?useSSL=false&amp;useUnicode=true&amp;characterEncoding=UTF-8&amp;serverTimezone=Asia/Shanghai</span></span><br><span class="line">    <span class="attr">driver-class-name:</span> <span class="string">com.mysql.cj.jdbc.Driver</span></span><br><span class="line">    <span class="attr">username:</span> <span class="string">root</span></span><br><span class="line">    <span class="attr">password:</span> <span class="string">root</span></span><br><span class="line"></span><br><span class="line"><span class="comment"># mybatis 配置内容</span></span><br><span class="line"><span class="attr">mybatis:</span></span><br><span class="line">  <span class="attr">config-location:</span> <span class="string">classpath:mybatis-config.xml</span> <span class="comment"># 配置 MyBatis 配置文件路径</span></span><br><span class="line">  <span class="attr">mapper-locations:</span> <span class="string">classpath:mapper/*.xml</span> <span class="comment"># 配置 Mapper XML 地址</span></span><br><span class="line">  <span class="attr">type-aliases-package:</span> <span class="string">cn.javadog.labs.springboot2.mybatis.xml.dataobject</span> <span class="comment"># 配置数据库实体包路径</span></span><br></pre></td></tr></table></figure><p>具体的每个配置项，胖友自己认真看下添加的所有注释噢。</p><h2 id="2-4-MyBatis-配置文件"><a href="#2-4-MyBatis-配置文件" class="headerlink" title="2.4 MyBatis 配置文件"></a>2.4 MyBatis 配置文件</h2><p>在 <code>resources</code>目录下，创建 <code>mybatis-config.xml</code>配置文件。配置如下：</p><figure class="highlight xml"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">&lt;?xml version="1.0" encoding="UTF-8" ?&gt;</span></span><br><span class="line"><span class="meta">&lt;!DOCTYPE <span class="meta-keyword">configuration</span> <span class="meta-keyword">PUBLIC</span> <span class="meta-string">"-//mybatis.org//DTD Config 3.0//EN"</span> <span class="meta-string">"http://mybatis.org/dtd/mybatis-3-config.dtd"</span>&gt;</span></span><br><span class="line"><span class="tag">&lt;<span class="name">configuration</span>&gt;</span></span><br><span class="line"></span><br><span class="line">    <span class="tag">&lt;<span class="name">settings</span>&gt;</span></span><br><span class="line">        <span class="comment">&lt;!-- 使用驼峰命名法转换字段。 --&gt;</span></span><br><span class="line">        <span class="tag">&lt;<span class="name">setting</span> <span class="attr">name</span>=<span class="string">"mapUnderscoreToCamelCase"</span> <span class="attr">value</span>=<span class="string">"true"</span>/&gt;</span></span><br><span class="line">    <span class="tag">&lt;/<span class="name">settings</span>&gt;</span></span><br><span class="line"></span><br><span class="line">    <span class="tag">&lt;<span class="name">typeAliases</span>&gt;</span></span><br><span class="line">        <span class="tag">&lt;<span class="name">typeAlias</span> <span class="attr">alias</span>=<span class="string">"Integer"</span> <span class="attr">type</span>=<span class="string">"java.lang.Integer"</span>/&gt;</span></span><br><span class="line">        <span class="tag">&lt;<span class="name">typeAlias</span> <span class="attr">alias</span>=<span class="string">"Long"</span> <span class="attr">type</span>=<span class="string">"java.lang.Long"</span>/&gt;</span></span><br><span class="line">        <span class="tag">&lt;<span class="name">typeAlias</span> <span class="attr">alias</span>=<span class="string">"HashMap"</span> <span class="attr">type</span>=<span class="string">"java.util.HashMap"</span>/&gt;</span></span><br><span class="line">        <span class="tag">&lt;<span class="name">typeAlias</span> <span class="attr">alias</span>=<span class="string">"LinkedHashMap"</span> <span class="attr">type</span>=<span class="string">"java.util.LinkedHashMap"</span>/&gt;</span></span><br><span class="line">        <span class="tag">&lt;<span class="name">typeAlias</span> <span class="attr">alias</span>=<span class="string">"ArrayList"</span> <span class="attr">type</span>=<span class="string">"java.util.ArrayList"</span>/&gt;</span></span><br><span class="line">        <span class="tag">&lt;<span class="name">typeAlias</span> <span class="attr">alias</span>=<span class="string">"LinkedList"</span> <span class="attr">type</span>=<span class="string">"java.util.LinkedList"</span>/&gt;</span></span><br><span class="line">    <span class="tag">&lt;/<span class="name">typeAliases</span>&gt;</span></span><br><span class="line"></span><br><span class="line"><span class="tag">&lt;/<span class="name">configuration</span>&gt;</span></span><br></pre></td></tr></table></figure><ul><li>因为在数据库中的表的字段，我们是使用下划线风格，而数据库实体的字段使用驼峰风格，所以通过 <code>mapUnderscoreToCamelCase = true</code> 来自动转换。</li><li><code>typeAliases</code> 用于在 <code>*Mapper.xml</code> 里设置 <code>parameterType</code>、<code>resultType</code>，但卡姆不建议胖友这样设置，因为自定义的别名，IDEA无法识别，你会看到xml里面各种飘红，而使用全路径时，IDEA能够解析并匹配字段，如果字段名有变更，能一眼就看到飘红的地方处理掉。<ul><li>上面xml中定义的别名，MyBatis启动时会自动设置一些常用的，如<code>Long</code>，只是使用的别名是小写的，具体实现胖友有兴趣可以看看 <a href="https://github.com/mybatis/mybatis-3/blob/master/src/main/java/org/apache/ibatis/type/TypeAliasRegistry.java" target="_blank" rel="noopener">TypeAliasRegistry</a></li></ul></li></ul><h2 id="2-5-UserDO"><a href="#2-5-UserDO" class="headerlink" title="2.5 UserDO"></a>2.5 UserDO</h2><p>创建 <code>UserDO.java</code> 类，用户 DO 。代码如下：</p><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">// UserDO.java</span></span><br><span class="line"></span><br><span class="line"><span class="meta">@Data</span></span><br><span class="line"><span class="meta">@Accessors</span>(chain = <span class="keyword">true</span>)</span><br><span class="line"><span class="keyword">public</span> <span class="class"><span class="keyword">class</span> <span class="title">UserDO</span> </span>&#123;</span><br><span class="line"></span><br><span class="line">    <span class="comment">/**</span></span><br><span class="line"><span class="comment">     * 用户编号</span></span><br><span class="line"><span class="comment">     */</span></span><br><span class="line">    <span class="keyword">private</span> Integer id;</span><br><span class="line">    </span><br><span class="line">    <span class="comment">/**</span></span><br><span class="line"><span class="comment">     * 账号</span></span><br><span class="line"><span class="comment">     */</span></span><br><span class="line">    <span class="keyword">private</span> String username;</span><br><span class="line">    </span><br><span class="line">    <span class="comment">/**</span></span><br><span class="line"><span class="comment">     * 密码（明文）</span></span><br><span class="line"><span class="comment">     *</span></span><br><span class="line"><span class="comment">     * ps：生产环境下，千万不要明文噢</span></span><br><span class="line"><span class="comment">     */</span></span><br><span class="line">    <span class="keyword">private</span> String password;</span><br><span class="line">    </span><br><span class="line">    <span class="comment">/**</span></span><br><span class="line"><span class="comment">     * 创建时间</span></span><br><span class="line"><span class="comment">     */</span></span><br><span class="line">    <span class="keyword">private</span> Date createTime;</span><br><span class="line"></span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><p>对应的创建表的 SQL 如下：</p><figure class="highlight sql"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">CREATE</span> <span class="keyword">TABLE</span> <span class="string">`mybatis_xml_users`</span> (</span><br><span class="line">  <span class="string">`id`</span> <span class="built_in">int</span>(<span class="number">11</span>) <span class="keyword">NOT</span> <span class="literal">NULL</span> AUTO_INCREMENT <span class="keyword">COMMENT</span> <span class="string">'用户编号'</span>,</span><br><span class="line">  <span class="string">`username`</span> <span class="built_in">varchar</span>(<span class="number">64</span>) <span class="keyword">COLLATE</span> utf8mb4_bin <span class="keyword">DEFAULT</span> <span class="literal">NULL</span> <span class="keyword">COMMENT</span> <span class="string">'账号'</span>,</span><br><span class="line">  <span class="string">`password`</span> <span class="built_in">varchar</span>(<span class="number">32</span>) <span class="keyword">COLLATE</span> utf8mb4_bin <span class="keyword">DEFAULT</span> <span class="literal">NULL</span> <span class="keyword">COMMENT</span> <span class="string">'密码'</span>,</span><br><span class="line">  <span class="string">`create_time`</span> datetime <span class="keyword">DEFAULT</span> <span class="literal">NULL</span> <span class="keyword">COMMENT</span> <span class="string">'创建时间'</span>,</span><br><span class="line">  PRIMARY <span class="keyword">KEY</span> (<span class="string">`id`</span>),</span><br><span class="line">  <span class="keyword">UNIQUE</span> <span class="keyword">KEY</span> <span class="string">`idx_username`</span> (<span class="string">`username`</span>)</span><br><span class="line">) <span class="keyword">ENGINE</span>=<span class="keyword">InnoDB</span> <span class="keyword">DEFAULT</span> <span class="keyword">CHARSET</span>=utf8mb4 <span class="keyword">COLLATE</span>=utf8mb4_bin;</span><br></pre></td></tr></table></figure><h2 id="2-6-UserMapper"><a href="#2-6-UserMapper" class="headerlink" title="2.6 UserMapper"></a>2.6 UserMapper</h2><p>创建 <code>UserMapper</code> 接口。代码如下：</p><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br></pre></td><td class="code"><pre><span class="line">&#x2F;&#x2F; UserMapper.java</span><br><span class="line"></span><br><span class="line">@Repository</span><br><span class="line">public interface UserMapper &#123;</span><br><span class="line"></span><br><span class="line">    int insert(UserDO user);</span><br><span class="line"></span><br><span class="line">    int updateById(UserDO user);</span><br><span class="line"></span><br><span class="line">    int deleteById(@Param(&quot;id&quot;) Integer id); &#x2F;&#x2F; 生产请使用标记删除，除非有点想不开。</span><br><span class="line"></span><br><span class="line">    UserDO selectById(@Param(&quot;id&quot;) Integer id);</span><br><span class="line"></span><br><span class="line">    UserDO selectByUsername(@Param(&quot;username&quot;) String username);</span><br><span class="line"></span><br><span class="line">    List&lt;UserDO&gt; selectByIds(@Param(&quot;ids&quot;) Collection&lt;Integer&gt; ids);</span><br><span class="line"></span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><ul><li><code>@Repository</code> 注解，用于标记是数据访问 Bean 对象。在 MyBatis 的接口，实际<strong>非必须</strong>，只是为了避免在 Service 中，<code>@Autowired</code> 注入时无需报警。</li><li><code>@Param</code> 注解，声明变量名。<ul><li>在方法为单参数时，<strong>非必须</strong>。</li><li>在方法为多参数时，<strong>必须</strong>。卡姆的编程习惯，<strong>禁止</strong>使用 Map 作为查询参数，因为无法通过方法的定义，很直观的看懂具体的用途。</li></ul></li><li>细心的胖友，肯定会发现例如说 <code>#selectByUsername(@Param(&quot;username&quot;) String username)</code> 等方法，是使用 <em>By</em> 字段结尾，这是为什么呢？一般情况下，在 SQL 中的 <code>WHERE</code> 条件字段，我们建议能够带在方法名后。原因无它，简单明了。如果是多个字段，可以使用 <em>AND</em> 分隔。当然，如果查询字段比较多，可能方法名会比较长。</li></ul><p>在 <code>resources/mapper</code> 路径下，创建 <code>UserMapper.xml</code> 配置文件。代码如下：</p><figure class="highlight xml"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br><span class="line">47</span><br><span class="line">48</span><br><span class="line">49</span><br><span class="line">50</span><br><span class="line">51</span><br><span class="line">52</span><br><span class="line">53</span><br><span class="line">54</span><br><span class="line">55</span><br><span class="line">56</span><br><span class="line">57</span><br><span class="line">58</span><br><span class="line">59</span><br><span class="line">60</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">&lt;?xml version="1.0" encoding="UTF-8"?&gt;</span></span><br><span class="line"><span class="meta">&lt;!DOCTYPE <span class="meta-keyword">mapper</span> <span class="meta-keyword">PUBLIC</span> <span class="meta-string">"-//mybatis.org//DTD Mapper 3.0//EN"</span> <span class="meta-string">"http://mybatis.org/dtd/mybatis-3-mapper.dtd"</span>&gt;</span></span><br><span class="line"><span class="tag">&lt;<span class="name">mapper</span> <span class="attr">namespace</span>=<span class="string">"cn.javadog.labs.springboot2.mybatis.xml.mapper.UserMapper"</span>&gt;</span></span><br><span class="line"></span><br><span class="line">    <span class="tag">&lt;<span class="name">sql</span> <span class="attr">id</span>=<span class="string">"FIELDS"</span>&gt;</span></span><br><span class="line">        id, username, password, create_time</span><br><span class="line">    <span class="tag">&lt;/<span class="name">sql</span>&gt;</span></span><br><span class="line"></span><br><span class="line">    <span class="tag">&lt;<span class="name">insert</span> <span class="attr">id</span>=<span class="string">"insert"</span> <span class="attr">parameterType</span>=<span class="string">"UserDO"</span> <span class="attr">useGeneratedKeys</span>=<span class="string">"true"</span> <span class="attr">keyProperty</span>=<span class="string">"id"</span>&gt;</span></span><br><span class="line">        INSERT INTO mybatis_xml_users (</span><br><span class="line">          username, password, create_time</span><br><span class="line">        ) VALUES (</span><br><span class="line">          #&#123;username&#125;, #&#123;password&#125;, #&#123;createTime&#125;</span><br><span class="line">        )</span><br><span class="line">    <span class="tag">&lt;/<span class="name">insert</span>&gt;</span></span><br><span class="line"></span><br><span class="line">    <span class="tag">&lt;<span class="name">update</span> <span class="attr">id</span>=<span class="string">"updateById"</span> <span class="attr">parameterType</span>=<span class="string">"UserDO"</span>&gt;</span></span><br><span class="line">        UPDATE mybatis_xml_users</span><br><span class="line">        <span class="tag">&lt;<span class="name">set</span>&gt;</span></span><br><span class="line">            <span class="tag">&lt;<span class="name">if</span> <span class="attr">test</span>=<span class="string">"username != null"</span>&gt;</span></span><br><span class="line">                , username = #&#123;username&#125;</span><br><span class="line">            <span class="tag">&lt;/<span class="name">if</span>&gt;</span></span><br><span class="line">            <span class="tag">&lt;<span class="name">if</span> <span class="attr">test</span>=<span class="string">"password != null"</span>&gt;</span></span><br><span class="line">                , password = #&#123;password&#125;</span><br><span class="line">            <span class="tag">&lt;/<span class="name">if</span>&gt;</span></span><br><span class="line">        <span class="tag">&lt;/<span class="name">set</span>&gt;</span></span><br><span class="line">        WHERE id = #&#123;id&#125;</span><br><span class="line">    <span class="tag">&lt;/<span class="name">update</span>&gt;</span></span><br><span class="line"></span><br><span class="line">    <span class="tag">&lt;<span class="name">delete</span> <span class="attr">id</span>=<span class="string">"deleteById"</span> <span class="attr">parameterType</span>=<span class="string">"Integer"</span>&gt;</span></span><br><span class="line">        DELETE FROM mybatis_xml_users</span><br><span class="line">        WHERE id = #&#123;id&#125;</span><br><span class="line">    <span class="tag">&lt;/<span class="name">delete</span>&gt;</span></span><br><span class="line"></span><br><span class="line">    <span class="tag">&lt;<span class="name">select</span> <span class="attr">id</span>=<span class="string">"selectById"</span> <span class="attr">parameterType</span>=<span class="string">"Integer"</span> <span class="attr">resultType</span>=<span class="string">"UserDO"</span>&gt;</span></span><br><span class="line">        SELECT</span><br><span class="line">            <span class="tag">&lt;<span class="name">include</span> <span class="attr">refid</span>=<span class="string">"FIELDS"</span> /&gt;</span></span><br><span class="line">        FROM mybatis_xml_users</span><br><span class="line">        WHERE id = #&#123;id&#125;</span><br><span class="line">    <span class="tag">&lt;/<span class="name">select</span>&gt;</span></span><br><span class="line"></span><br><span class="line">    <span class="tag">&lt;<span class="name">select</span> <span class="attr">id</span>=<span class="string">"selectByUsername"</span> <span class="attr">parameterType</span>=<span class="string">"String"</span> <span class="attr">resultType</span>=<span class="string">"UserDO"</span>&gt;</span></span><br><span class="line">        SELECT</span><br><span class="line">            <span class="tag">&lt;<span class="name">include</span> <span class="attr">refid</span>=<span class="string">"FIELDS"</span> /&gt;</span></span><br><span class="line">        FROM mybatis_xml_users</span><br><span class="line">        WHERE username = #&#123;username&#125;</span><br><span class="line">        LIMIT 1</span><br><span class="line">    <span class="tag">&lt;/<span class="name">select</span>&gt;</span></span><br><span class="line"></span><br><span class="line">    <span class="tag">&lt;<span class="name">select</span> <span class="attr">id</span>=<span class="string">"selectByIds"</span> <span class="attr">resultType</span>=<span class="string">"UserDO"</span>&gt;</span></span><br><span class="line">        SELECT</span><br><span class="line">            <span class="tag">&lt;<span class="name">include</span> <span class="attr">refid</span>=<span class="string">"FIELDS"</span> /&gt;</span></span><br><span class="line">        FROM mybatis_xml_users</span><br><span class="line">        WHERE id IN</span><br><span class="line">            <span class="tag">&lt;<span class="name">foreach</span> <span class="attr">item</span>=<span class="string">"id"</span> <span class="attr">collection</span>=<span class="string">"ids"</span> <span class="attr">separator</span>=<span class="string">","</span> <span class="attr">open</span>=<span class="string">"("</span> <span class="attr">close</span>=<span class="string">")"</span> <span class="attr">index</span>=<span class="string">""</span>&gt;</span></span><br><span class="line">                #&#123;id&#125;</span><br><span class="line">            <span class="tag">&lt;/<span class="name">foreach</span>&gt;</span></span><br><span class="line">    <span class="tag">&lt;/<span class="name">select</span>&gt;</span></span><br><span class="line"></span><br><span class="line"><span class="tag">&lt;/<span class="name">mapper</span>&gt;</span></span><br></pre></td></tr></table></figure><ul><li>建议 1 ：对于绝大多数查询，我们是返回统一字段，所以可以使用 <code>&lt;sql /&gt;</code> 标签，定义 SQL 段。对于性能或者查询字段比较大的查询，按需要的字段查询。</li><li>建议 2 ：对于数据库的关键字，使用大写。例如说，<code>SELECT</code>、<code>WHERE</code> 等等。</li><li>建议 3 ：基本是每“块”数据库关键字占用一行，胖友可以看看卡姆写的每一行示例。一定要排版干净，毕竟我们是有代码洁癖的男孩子。</li><li>建议4：表名尽量使用 “`“ 包起来，避免mybatis或者mysql的关键字导致一些意料之外的问题。比如卡姆一开始使用的表名是 <code>mybatis-xml-users</code>，没有使用 “`“ 包起来，就GG了。</li></ul><h2 id="2-7-简单测试"><a href="#2-7-简单测试" class="headerlink" title="2.7 简单测试"></a>2.7 简单测试</h2><p>创建 <code>UserMapperTest</code>测试类，我们来测试一下简单的 UserMapper 的每个操作。代码如下：</p><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">// UserMapperTest.java</span></span><br><span class="line"></span><br><span class="line"><span class="meta">@RunWith</span>(SpringRunner<span class="class">.<span class="keyword">class</span>)</span></span><br><span class="line"><span class="class">@<span class="title">SpringBootTest</span>(<span class="title">classes</span> </span>= MyBatisXmlApplication<span class="class">.<span class="keyword">class</span>)</span></span><br><span class="line"><span class="class"><span class="title">public</span> <span class="title">class</span> <span class="title">UserMapperTest</span> </span>&#123;</span><br><span class="line"></span><br><span class="line">    <span class="meta">@Autowired</span></span><br><span class="line">    <span class="keyword">private</span> UserMapper userMapper;</span><br><span class="line"></span><br><span class="line">    <span class="meta">@Test</span></span><br><span class="line">    <span class="function"><span class="keyword">public</span> <span class="keyword">void</span> <span class="title">testInsert</span><span class="params">()</span> </span>&#123;</span><br><span class="line">        UserDO user = <span class="keyword">new</span> UserDO().setUsername(UUID.randomUUID().toString())</span><br><span class="line">                .setPassword(<span class="string">"mybatis-xml"</span>).setCreateTime(<span class="keyword">new</span> Date());</span><br><span class="line">        userMapper.insert(user);</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    <span class="meta">@Test</span></span><br><span class="line">    <span class="function"><span class="keyword">public</span> <span class="keyword">void</span> <span class="title">testUpdateById</span><span class="params">()</span> </span>&#123;</span><br><span class="line">        UserDO updateUser = <span class="keyword">new</span> UserDO().setId(<span class="number">1</span>)</span><br><span class="line">                .setPassword(<span class="string">"mybatis-xml"</span>);</span><br><span class="line">        userMapper.updateById(updateUser);</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    <span class="meta">@Test</span></span><br><span class="line">    <span class="function"><span class="keyword">public</span> <span class="keyword">void</span> <span class="title">testDeleteById</span><span class="params">()</span> </span>&#123;</span><br><span class="line">        userMapper.deleteById(<span class="number">2</span>);</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    <span class="meta">@Test</span></span><br><span class="line">    <span class="function"><span class="keyword">public</span> <span class="keyword">void</span> <span class="title">testSelectById</span><span class="params">()</span> </span>&#123;</span><br><span class="line">        userMapper.selectById(<span class="number">1</span>);</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    <span class="meta">@Test</span></span><br><span class="line">    <span class="function"><span class="keyword">public</span> <span class="keyword">void</span> <span class="title">testSelectByUsername</span><span class="params">()</span> </span>&#123;</span><br><span class="line">        userMapper.selectByUsername(<span class="string">"calm"</span>);</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    <span class="meta">@Test</span></span><br><span class="line">    <span class="function"><span class="keyword">public</span> <span class="keyword">void</span> <span class="title">testSelectByIds</span><span class="params">()</span> </span>&#123;</span><br><span class="line">        List&lt;UserDO&gt; users = userMapper.selectByIds(Arrays.asList(<span class="number">1</span>, <span class="number">3</span>));</span><br><span class="line">        System.out.println(<span class="string">"users："</span> + users.size());</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><blockquote><p>如果胖友嫌弃手写 MyBatis XML 很麻烦，可以考虑使用 <a href="https://github.com/mybatis/generator" target="_blank" rel="noopener">MyBatis Generator (MBG)</a> 或者 <a href="https://github.com/abel533/Mapper/wiki/4.1.mappergenerator" target="_blank" rel="noopener">mappergenerator</a>，这类工具还是蛮多的，或者自己手写一个轮子也未尝不可😂</p></blockquote><h1 id="3-MyBatis-注解"><a href="#3-MyBatis-注解" class="headerlink" title="3. MyBatis + 注解"></a>3. MyBatis + 注解</h1><p>大多数情况下，卡姆并不推荐使用注解的方式编写 SQL 。一方面，SQL 无法很好的排版。另一方面，会导致 Mapper 接口很长很乱。但如果你对mybatis的源码很熟悉的话，使用注解写一些简单的静态SQL，有时候还是蛮方便的😄。</p><blockquote><p>FROM <a href="https://mybatis.org/mybatis-3/zh/java-api.html" target="_blank" rel="noopener">https://mybatis.org/mybatis-3/zh/java-api.html</a></p><p>因为最初设计时，MyBatis 是一个 XML 驱动的框架。配置信息是基于 XML 的，而且映射语句也是定义在 XML 中的。而到了 MyBatis 3，就有新选择了。MyBatis 3 构建在全面且强大的基于 Java 语言的配置 API 之上。这个配置 API 是基于 XML 的 MyBatis 配置的基础，也是新的基于注解配置的基础。注解提供了一种简单的方式来实现简单映射语句，而不会引入大量的开销。</p><p><strong>不幸的是，Java 注解的的表达力和灵活性十分有限。</strong>尽管很多时间都花在调查、设计和试验上，最强大的 MyBatis 映射并不能用注解来构建——并不是在开玩笑，的确是这样。比方说，C#属性就没有这些限制，因此 MyBatis.NET 将会比 XML 有更丰富的选择。也就是说，基于 Java 注解的配置离不开它的特性。</p></blockquote><ul><li>间接表述不是很推荐使用 MyBatis 注解的方式。</li></ul><blockquote><p>示例代码对应仓库：<a href="https://github.com/yuyong725/labs-springboot2/tree/master/labs-springboot2-data-access/labs-springboot2-mybatis/labs-springboot2-mybatis-annotation" target="_blank" rel="noopener">labs-springboot2-mybatis-annotation</a> 。</p></blockquote><h2 id="3-1-差异部分"><a href="#3-1-差异部分" class="headerlink" title="3.1 差异部分"></a>3.1 差异部分</h2><p>考虑到胖友已经看过 <a href="https://calm_java.gitee.io/blog/2020/01/08/labs-springboot2-mybatis/">「2. MyBatis + XML」</a> 小节的内容，我们在这个小节主要说下差异的地方。</p><p><strong>1、application.yaml</strong></p><p>在 <code>application.yaml</code> 配置文件中，我们可以删除 <code>mapper-locations</code> 配置项。</p><p>当然，如果胖友想 XML 和注解一起使用，可以保留该配置项。</p><p><strong>2、UserMapper.xml</strong></p><p>可以删除 <code>UserMapper.xml</code> 配置文件。不过需要在 <code>UserMapper</code> 接口上，通过注解声明 SQL 操作。具体见 <a href="https://calm_java.gitee.io/blog/2020/01/08/labs-springboot2-mybatis/">「3.2 UserMapper」</a> 。</p><h2 id="3-2-UserMapper"><a href="#3-2-UserMapper" class="headerlink" title="3.2 UserMapper"></a>3.2 UserMapper</h2><p>创建 <code>UserMapper</code> 接口。代码如下：</p><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">// UserMapper.java</span></span><br><span class="line"></span><br><span class="line"><span class="meta">@Repository</span></span><br><span class="line"><span class="keyword">public</span> <span class="class"><span class="keyword">interface</span> <span class="title">UserMapper</span> </span>&#123;</span><br><span class="line"></span><br><span class="line">    <span class="meta">@Insert</span>(<span class="string">"INSERT INTO mybatis_annotation_users(username, password, create_time) VALUES(#&#123;username&#125;, #&#123;password&#125;, #&#123;createTime&#125;)"</span>)</span><br><span class="line">    <span class="meta">@Options</span>(useGeneratedKeys = <span class="keyword">true</span>, keyProperty = <span class="string">"id"</span>, keyColumn = <span class="string">"id"</span>)</span><br><span class="line">    <span class="function"><span class="keyword">int</span> <span class="title">insert</span><span class="params">(UserDO user)</span></span>;</span><br><span class="line"></span><br><span class="line">    <span class="meta">@Update</span>(value = &#123;</span><br><span class="line">            <span class="string">"&lt;script&gt;"</span>,</span><br><span class="line">            <span class="string">"UPDATE mybatis_annotation_users"</span>,</span><br><span class="line">            <span class="string">"&lt;set&gt;"</span>,</span><br><span class="line">            <span class="string">"&lt;if test='username != null'&gt;, username = #&#123;username&#125;&lt;/if&gt;"</span>,</span><br><span class="line">            <span class="string">"&lt;if test='password != null'&gt;, password = #&#123;password&#125;&lt;/if&gt;"</span>,</span><br><span class="line">            <span class="string">"&lt;/set&gt;"</span>,</span><br><span class="line">            <span class="string">"&lt;/script&gt;"</span></span><br><span class="line">    &#125;)</span><br><span class="line">    <span class="function"><span class="keyword">int</span> <span class="title">updateById</span><span class="params">(UserDO user)</span></span>;</span><br><span class="line"></span><br><span class="line">    <span class="meta">@Insert</span>(<span class="string">"DELETE FROM mybatis_annotation_users WHERE id = #&#123;id&#125;"</span>)</span><br><span class="line">    <span class="function"><span class="keyword">int</span> <span class="title">deleteById</span><span class="params">(@Param(<span class="string">"id"</span>)</span> Integer id)</span>; <span class="comment">// 生产请使用标记删除，除非有点想不开，嘿嘿。</span></span><br><span class="line"></span><br><span class="line">    <span class="meta">@Select</span>(<span class="string">"SELECT username, password, create_time FROM mybatis_annotation_users WHERE id = #&#123;id&#125;"</span>)</span><br><span class="line">    <span class="function">UserDO <span class="title">selectById</span><span class="params">(@Param(<span class="string">"id"</span>)</span> Integer id)</span>;</span><br><span class="line"></span><br><span class="line">    <span class="meta">@Select</span>(<span class="string">"SELECT username, password, create_time FROM mybatis_annotation_users WHERE username = #&#123;username&#125;"</span>)</span><br><span class="line">    <span class="function">UserDO <span class="title">selectByUsername</span><span class="params">(@Param(<span class="string">"username"</span>)</span> String username)</span>;</span><br><span class="line"></span><br><span class="line">    <span class="meta">@Select</span>(value = &#123;</span><br><span class="line">            <span class="string">"&lt;script&gt;"</span>,</span><br><span class="line">            <span class="string">"SELECT username, password, create_time FROM mybatis_annotation_users"</span>,</span><br><span class="line">            <span class="string">"WHERE id IN"</span>,</span><br><span class="line">            <span class="string">"&lt;foreach item='id' collection='ids' separator=',' open='(' close=')' index=''&gt;"</span>,</span><br><span class="line">            <span class="string">"#&#123;id&#125;"</span>,</span><br><span class="line">            <span class="string">"&lt;/foreach&gt;"</span>,</span><br><span class="line">            <span class="string">"&lt;/script&gt;"</span></span><br><span class="line">    &#125;)</span><br><span class="line">    <span class="function">List&lt;UserDO&gt; <span class="title">selectByIds</span><span class="params">(@Param(<span class="string">"ids"</span>)</span> Collection&lt;Integer&gt; ids)</span>;</span><br><span class="line"></span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><ul><li>是不是发现整个 Mapper 接口看起来乱乱的，并且 SQL 的排版也不尽如人意。</li><li>对于使用 OGNL 编写动态 SQL ，也特别难受。具体怎么用，胖友可以看看 <a href="https://www.cnblogs.com/EasonJim/p/7449699.html" target="_blank" rel="noopener">《MyBatis 在注解上使用动态 SQL》</a> 文章。反正艿艿不是想写第二遍了。</li></ul><h2 id="3-3-简单测试"><a href="#3-3-简单测试" class="headerlink" title="3.3 简单测试"></a>3.3 简单测试</h2><p>具体的测试，还是使用 <code>UserMapperTest</code>测试类，直接运行每个测试方法即可。</p><h1 id="4-MyBatis-Plus"><a href="#4-MyBatis-Plus" class="headerlink" title="4. MyBatis-Plus"></a>4. MyBatis-Plus</h1><blockquote><p>示例代码对应仓库：<a href="https://github.com/yuyong725/labs-springboot2/tree/master/labs-springboot2-data-access/labs-springboot2-mybatis/labs-springboot2-mybatis-plus" target="_blank" rel="noopener">labs-springboot2-mybatis-plus</a> 。</p></blockquote><p>本小节，我们会使用 <code>mybatis-plus-boot-starter</code>自动化配置 MyBatis-Plus 的配置。同时，演示如何使用 MyBatis-Plus 实现我们在 <a href="https://calm_java.gitee.io/blog/2020/01/08/labs-springboot2-mybatis/">「2. MyBatis + XML」</a> 演示的各种 CRUD 的操作。</p><h2 id="4-1-引入依赖"><a href="#4-1-引入依赖" class="headerlink" title="4.1 引入依赖"></a>4.1 引入依赖</h2><p>在 <code>pom.xml</code> 文件中，引入相关依赖。</p><figure class="highlight xml"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">&lt;?xml version="1.0" encoding="UTF-8"?&gt;</span></span><br><span class="line"><span class="tag">&lt;<span class="name">project</span> <span class="attr">xmlns</span>=<span class="string">"http://maven.apache.org/POM/4.0.0"</span></span></span><br><span class="line"><span class="tag">         <span class="attr">xmlns:xsi</span>=<span class="string">"http://www.w3.org/2001/XMLSchema-instance"</span></span></span><br><span class="line"><span class="tag">         <span class="attr">xsi:schemaLocation</span>=<span class="string">"http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"</span>&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">parent</span>&gt;</span></span><br><span class="line">        <span class="tag">&lt;<span class="name">artifactId</span>&gt;</span>labs-springboot2-mybatis<span class="tag">&lt;/<span class="name">artifactId</span>&gt;</span></span><br><span class="line">        <span class="tag">&lt;<span class="name">groupId</span>&gt;</span>cn.javadog<span class="tag">&lt;/<span class="name">groupId</span>&gt;</span></span><br><span class="line">        <span class="tag">&lt;<span class="name">version</span>&gt;</span>1.0-SNAPSHOT<span class="tag">&lt;/<span class="name">version</span>&gt;</span></span><br><span class="line">    <span class="tag">&lt;/<span class="name">parent</span>&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">modelVersion</span>&gt;</span>4.0.0<span class="tag">&lt;/<span class="name">modelVersion</span>&gt;</span></span><br><span class="line"></span><br><span class="line">    <span class="tag">&lt;<span class="name">artifactId</span>&gt;</span>labs-springboot2-mybatis-plus<span class="tag">&lt;/<span class="name">artifactId</span>&gt;</span></span><br><span class="line"></span><br><span class="line">    <span class="tag">&lt;<span class="name">dependencies</span>&gt;</span></span><br><span class="line">        <span class="comment">&lt;!-- 实现对数据库连接池的自动化配置 --&gt;</span></span><br><span class="line">        <span class="tag">&lt;<span class="name">dependency</span>&gt;</span></span><br><span class="line">            <span class="tag">&lt;<span class="name">groupId</span>&gt;</span>org.springframework.boot<span class="tag">&lt;/<span class="name">groupId</span>&gt;</span></span><br><span class="line">            <span class="tag">&lt;<span class="name">artifactId</span>&gt;</span>spring-boot-starter-jdbc<span class="tag">&lt;/<span class="name">artifactId</span>&gt;</span></span><br><span class="line">        <span class="tag">&lt;/<span class="name">dependency</span>&gt;</span></span><br><span class="line">        <span class="comment">&lt;!-- 本示例，我们使用 MySQL --&gt;</span></span><br><span class="line">        <span class="tag">&lt;<span class="name">dependency</span>&gt;</span></span><br><span class="line">            <span class="tag">&lt;<span class="name">groupId</span>&gt;</span>mysql<span class="tag">&lt;/<span class="name">groupId</span>&gt;</span></span><br><span class="line">            <span class="tag">&lt;<span class="name">artifactId</span>&gt;</span>mysql-connector-java<span class="tag">&lt;/<span class="name">artifactId</span>&gt;</span></span><br><span class="line">        <span class="tag">&lt;/<span class="name">dependency</span>&gt;</span></span><br><span class="line"></span><br><span class="line">        <span class="comment">&lt;!-- 实现对 MyBatis Plus 的自动化配置，不需要 mybatis-spring-boot-starter  --&gt;</span></span><br><span class="line">        <span class="tag">&lt;<span class="name">dependency</span>&gt;</span></span><br><span class="line">            <span class="tag">&lt;<span class="name">groupId</span>&gt;</span>com.baomidou<span class="tag">&lt;/<span class="name">groupId</span>&gt;</span></span><br><span class="line">            <span class="tag">&lt;<span class="name">artifactId</span>&gt;</span>mybatis-plus-boot-starter<span class="tag">&lt;/<span class="name">artifactId</span>&gt;</span></span><br><span class="line">            <span class="tag">&lt;<span class="name">version</span>&gt;</span>3.2.0<span class="tag">&lt;/<span class="name">version</span>&gt;</span></span><br><span class="line">        <span class="tag">&lt;/<span class="name">dependency</span>&gt;</span></span><br><span class="line"></span><br><span class="line">        <span class="comment">&lt;!-- 方便等会写单元测试 --&gt;</span></span><br><span class="line">        <span class="tag">&lt;<span class="name">dependency</span>&gt;</span></span><br><span class="line">            <span class="tag">&lt;<span class="name">groupId</span>&gt;</span>org.springframework.boot<span class="tag">&lt;/<span class="name">groupId</span>&gt;</span></span><br><span class="line">            <span class="tag">&lt;<span class="name">artifactId</span>&gt;</span>spring-boot-starter-test<span class="tag">&lt;/<span class="name">artifactId</span>&gt;</span></span><br><span class="line">            <span class="tag">&lt;<span class="name">scope</span>&gt;</span>test<span class="tag">&lt;/<span class="name">scope</span>&gt;</span></span><br><span class="line">        <span class="tag">&lt;/<span class="name">dependency</span>&gt;</span></span><br><span class="line"></span><br><span class="line">        <span class="tag">&lt;<span class="name">dependency</span>&gt;</span></span><br><span class="line">            <span class="tag">&lt;<span class="name">groupId</span>&gt;</span>org.projectlombok<span class="tag">&lt;/<span class="name">groupId</span>&gt;</span></span><br><span class="line">            <span class="tag">&lt;<span class="name">artifactId</span>&gt;</span>lombok<span class="tag">&lt;/<span class="name">artifactId</span>&gt;</span></span><br><span class="line">        <span class="tag">&lt;/<span class="name">dependency</span>&gt;</span></span><br><span class="line">    <span class="tag">&lt;/<span class="name">dependencies</span>&gt;</span></span><br><span class="line"></span><br><span class="line"><span class="tag">&lt;/<span class="name">project</span>&gt;</span></span><br></pre></td></tr></table></figure><ul><li>相比来说，将 <code>mybatis-spring-boot-starter</code> 替换成 <code>mybatis-plus-boot-starter</code> 。</li></ul><h2 id="4-2-MyBatisPlusApplication"><a href="#4-2-MyBatisPlusApplication" class="headerlink" title="4.2 MyBatisPlusApplication"></a>4.2 MyBatisPlusApplication</h2><p>创建 <code>MyBatisPlusApplication</code> 类，配置 <code>@MapperScan</code> 注解，扫描对应 Mapper 接口所在的包路径。代码如下：</p><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br></pre></td><td class="code"><pre><span class="line">&#x2F;&#x2F; MyBatisPlusApplication.java</span><br><span class="line"></span><br><span class="line">@SpringBootApplication</span><br><span class="line">@MapperScan(basePackages &#x3D; &quot;cn.javadog.labs.springboot2.mybatis.plus.mapper&quot;)</span><br><span class="line">public class MyBatisPlusApplication &#123;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><ul><li>和 <a href="https://calm_java.gitee.io/blog/2020/01/08/labs-springboot2-mybatis/">「2.2 Application」</a> 一致。</li></ul><h2 id="4-3-应用配置文件"><a href="#4-3-应用配置文件" class="headerlink" title="4.3 应用配置文件"></a>4.3 应用配置文件</h2><p>在 <code>resources</code> 目录下，创建 <code>application.yaml</code> 配置文件。配置如下：</p><figure class="highlight yaml"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br></pre></td><td class="code"><pre><span class="line"><span class="attr">spring:</span></span><br><span class="line">  <span class="comment"># datasource 数据源配置内容</span></span><br><span class="line">  <span class="attr">datasource:</span></span><br><span class="line">    <span class="attr">url:</span> <span class="string">jdbc:mysql://127.0.0.1:3306/labs-springboot2?useSSL=false&amp;useUnicode=true&amp;characterEncoding=UTF-8&amp;serverTimezone=Asia/Shanghai</span></span><br><span class="line">    <span class="attr">driver-class-name:</span> <span class="string">com.mysql.cj.jdbc.Driver</span></span><br><span class="line">    <span class="attr">username:</span> <span class="string">root</span></span><br><span class="line">    <span class="attr">password:</span> <span class="string">root</span></span><br><span class="line"></span><br><span class="line"><span class="comment"># mybatis-plus 配置内容</span></span><br><span class="line"><span class="attr">mybatis-plus:</span></span><br><span class="line">  <span class="attr">configuration:</span></span><br><span class="line">    <span class="attr">map-underscore-to-camel-case:</span> <span class="literal">true</span> <span class="comment"># 虽然默认为 true ，但是还是显示去指定下。</span></span><br><span class="line">  <span class="attr">global-config:</span></span><br><span class="line">    <span class="attr">db-config:</span></span><br><span class="line">      <span class="attr">id-type:</span> <span class="string">auto</span> <span class="comment"># ID 主键自增</span></span><br><span class="line">      <span class="attr">logic-delete-value:</span> <span class="number">1</span> <span class="comment"># 逻辑已删除值(默认为 1)</span></span><br><span class="line">      <span class="attr">logic-not-delete-value:</span> <span class="number">0</span> <span class="comment"># 逻辑未删除值(默认为 0)</span></span><br><span class="line">  <span class="attr">mapper-locations:</span> <span class="string">classpath*:mapper/*.xml</span></span><br><span class="line">  <span class="attr">type-aliases-package:</span> <span class="string">cn.javadog.labs.springboot2.mybatis.plus.dataobject</span></span><br><span class="line"></span><br><span class="line"><span class="comment"># logging</span></span><br><span class="line"><span class="attr">logging:</span></span><br><span class="line">  <span class="attr">level:</span></span><br><span class="line">    <span class="comment"># dao 开启 debug 模式 mybatis 输入 sql</span></span><br><span class="line">    <span class="attr">cn.javadog:</span> <span class="string">debug</span></span><br></pre></td></tr></table></figure><ul><li>将 <code>mybatis</code> 替换成 <code>mybatis-plus</code> 配置项目。实际上，如果老项目在用 <code>mybatis-spring-boot-starter</code> 的话，直接将 <code>mybatis</code> 修改成 <code>mybatis-plus</code> 即可。</li><li>相比 <code>mybatis</code> 配置项来说，<code>mybatis-plus</code> 增加了更多配置项，也因此我们无需在配置 <code>mybatis-config.xml</code> 配置文件。</li><li>更多的 MyBatis-Plus 配置项，可以看看 <a href="https://mybatis.plus/config/#mapperlocations" target="_blank" rel="noopener">MyBatis-Plus 使用配置</a> 。</li><li>配置 <code>logging</code> 的原因是，方便我们看到 MyBatis-Plus 自动生成的 SQL 。生产环境下，记得关闭噢。</li></ul><h2 id="4-4-UserDO"><a href="#4-4-UserDO" class="headerlink" title="4.4 UserDO"></a>4.4 UserDO</h2><p>创建 <code>UserDO</code> 类，用户 DO 。代码如下：</p><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">// UserDO.java</span></span><br><span class="line"><span class="meta">@Data</span></span><br><span class="line"><span class="meta">@Accessors</span>(chain = <span class="keyword">true</span>)</span><br><span class="line"><span class="meta">@TableName</span>(value = <span class="string">"mybatis_plus_users"</span>)</span><br><span class="line"><span class="keyword">public</span> <span class="class"><span class="keyword">class</span> <span class="title">UserDO</span> </span>&#123;</span><br><span class="line"></span><br><span class="line">    <span class="comment">/**</span></span><br><span class="line"><span class="comment">     * 用户编号</span></span><br><span class="line"><span class="comment">     */</span></span><br><span class="line">    <span class="keyword">private</span> Integer id;</span><br><span class="line">  </span><br><span class="line">    <span class="comment">/**</span></span><br><span class="line"><span class="comment">     * 账号</span></span><br><span class="line"><span class="comment">     */</span></span><br><span class="line">    <span class="keyword">private</span> String username;</span><br><span class="line">  </span><br><span class="line">    <span class="comment">/**</span></span><br><span class="line"><span class="comment">     * 密码（明文）</span></span><br><span class="line"><span class="comment">     *</span></span><br><span class="line"><span class="comment">     * ps：生产环境下，千万不要明文噢</span></span><br><span class="line"><span class="comment">     */</span></span><br><span class="line">    <span class="keyword">private</span> String password;</span><br><span class="line">  </span><br><span class="line">    <span class="comment">/**</span></span><br><span class="line"><span class="comment">     * 创建时间</span></span><br><span class="line"><span class="comment">     */</span></span><br><span class="line">    <span class="keyword">private</span> Date createTime;</span><br><span class="line">  </span><br><span class="line">    <span class="comment">/**</span></span><br><span class="line"><span class="comment">     * 是否删除</span></span><br><span class="line"><span class="comment">     */</span></span><br><span class="line">    <span class="meta">@TableLogic</span></span><br><span class="line">    <span class="keyword">private</span> Integer deleted;</span><br><span class="line"></span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><ul><li>相比 <a href="https://calm_java.gitee.io/blog/2020/01/08/labs-springboot2-mybatis/">「2.5 UserDO」</a> 来说，主要有两点差别。</li><li>增加了 <code>@TableName</code> 注解，设置了 UserDO 对应的表名是 <code>users</code> 。毕竟，我们要使用 MyBatis-Plus 给咱自动生成 CRUD 操作。</li><li>增加了 <code>deleted</code>字段，并添加了<code>@TableLogic</code>注解，设置该字段为逻辑删除的标记。<ul><li>在 <code>application.yaml</code> 配置文件中，我们配置了删除（<code>logic-delete-value = 1</code>）和未删除（<code>logic-not-delete-value = 0</code>）。当然，也可以通过注解的 <code>value</code> 和 <code>delval</code> 来定义未删除和删除。</li><li>具体关于 MyBatis-Plus 的逻辑删除功能，看下 <a href="https://mybatis.plus/guide/logic-delete.html" target="_blank" rel="noopener">逻辑删除</a> 部分的文档。</li></ul></li></ul><p>对应的创建表的 SQL 如下：</p><figure class="highlight sql"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">CREATE</span> <span class="keyword">TABLE</span> <span class="string">`mybatis_plus_users`</span> (</span><br><span class="line">  <span class="string">`id`</span> <span class="built_in">int</span>(<span class="number">11</span>) <span class="keyword">NOT</span> <span class="literal">NULL</span> AUTO_INCREMENT <span class="keyword">COMMENT</span> <span class="string">'用户编号'</span>,</span><br><span class="line">  <span class="string">`username`</span> <span class="built_in">varchar</span>(<span class="number">64</span>) <span class="keyword">COLLATE</span> utf8mb4_bin <span class="keyword">DEFAULT</span> <span class="literal">NULL</span> <span class="keyword">COMMENT</span> <span class="string">'账号'</span>,</span><br><span class="line">  <span class="string">`password`</span> <span class="built_in">varchar</span>(<span class="number">32</span>) <span class="keyword">COLLATE</span> utf8mb4_bin <span class="keyword">DEFAULT</span> <span class="literal">NULL</span> <span class="keyword">COMMENT</span> <span class="string">'密码'</span>,</span><br><span class="line">  <span class="string">`create_time`</span> datetime <span class="keyword">DEFAULT</span> <span class="literal">NULL</span> <span class="keyword">COMMENT</span> <span class="string">'创建时间'</span>,</span><br><span class="line">  <span class="string">`deleted`</span> <span class="built_in">bit</span>(<span class="number">1</span>) <span class="keyword">DEFAULT</span> <span class="literal">NULL</span> <span class="keyword">COMMENT</span> <span class="string">'是否删除。0-未删除；1-删除'</span>,</span><br><span class="line">  PRIMARY <span class="keyword">KEY</span> (<span class="string">`id`</span>),</span><br><span class="line">  <span class="keyword">UNIQUE</span> <span class="keyword">KEY</span> <span class="string">`idx_username`</span> (<span class="string">`username`</span>)</span><br><span class="line">) <span class="keyword">ENGINE</span>=<span class="keyword">InnoDB</span> <span class="keyword">DEFAULT</span> <span class="keyword">CHARSET</span>=utf8mb4 <span class="keyword">COLLATE</span>=utf8mb4_bin;</span><br></pre></td></tr></table></figure><h2 id="4-5-UserMapper"><a href="#4-5-UserMapper" class="headerlink" title="4.5 UserMapper"></a>4.5 UserMapper</h2><p>创建 <code>UserMapper</code> 接口。代码如下：</p><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">// UserMapper.java</span></span><br><span class="line"></span><br><span class="line"><span class="meta">@Repository</span></span><br><span class="line"><span class="keyword">public</span> <span class="class"><span class="keyword">interface</span> <span class="title">UserMapper</span> <span class="keyword">extends</span> <span class="title">BaseMapper</span>&lt;<span class="title">UserDO</span>&gt; </span>&#123;</span><br><span class="line"></span><br><span class="line">    <span class="function"><span class="keyword">default</span> UserDO <span class="title">selectByUsername</span><span class="params">(String username)</span> </span>&#123;</span><br><span class="line">        <span class="keyword">return</span> selectOne(<span class="keyword">new</span> QueryWrapper&lt;UserDO&gt;().eq(<span class="string">"username"</span>, username));</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    <span class="function">List&lt;UserDO&gt; <span class="title">selectByIds</span><span class="params">(@Param(<span class="string">"ids"</span>)</span> Collection&lt;Integer&gt; ids)</span>;</span><br><span class="line"></span><br><span class="line">    <span class="function"><span class="keyword">default</span> List&lt;UserDO&gt; <span class="title">selectByIdsWithWrapper</span><span class="params">(Collection&lt;Integer&gt; ids)</span> </span>&#123;</span><br><span class="line">        <span class="keyword">return</span> selectList(<span class="keyword">new</span> QueryWrapper&lt;UserDO&gt;().in(<span class="string">"id"</span>, ids));</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    <span class="function"><span class="keyword">default</span> IPage&lt;UserDO&gt; <span class="title">selectPageByCreateTime</span><span class="params">(IPage&lt;UserDO&gt; page, Date createTime)</span> </span>&#123;</span><br><span class="line">        <span class="keyword">return</span> selectPage(page,</span><br><span class="line">                <span class="keyword">new</span> QueryWrapper&lt;UserDO&gt;().gt(<span class="string">"create_time"</span>, createTime)</span><br><span class="line"><span class="comment">//                new QueryWrapper&lt;UserDO&gt;().like("username", "46683d9d")</span></span><br><span class="line">        );</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><ul><li><p>还是老样子，我们来比较下 <a href="https://calm_java.gitee.io/blog/2020/01/08/labs-springboot2-mybatis/">「2.6 UserMapper」</a> 接口。</p></li><li><p>继承了 <code>com.baomidou.mybatisplus.core.mapper.BaseMapper&lt;T&gt;</code> 接口，这样常规的 CRUD 操作，MyBatis-Plus 就可以替我们自动生成。一般来说，开发 CRUD 业务的时候，最枯燥的就是要写 CRUD 的常用 SQL ，完全跟不上艿艿的思绪哈。</p><ul><li>因为继承了 BaseMapper 接口，所以我们删除了 <code>#insert(UserDO user)</code>、<code>#updateById(UserDO user)</code>、<code>#deleteById(@Param(&quot;id&quot;) Integer id)</code>、<code>#selectById(@Param(&quot;id&quot;) Integer id)</code> 四个 CRUD 方法。</li><li>更多 BaseMapper 已经提供好的接口方法，可以看看 <a href="https://mybatis.plus/guide/crud-interface.html#mapper-crud-接口" target="_blank" rel="noopener">《MyBatis-Plus 文档 —— CRUD 接口》</a> 。</li></ul></li><li><p>对于 <code>#selectByUsername(@Param(&quot;username&quot;) String username)</code> 方法，我们使用了</p><p><code>com.baomidou.mybatisplus.core.conditions.query.QueryWrapper&lt;T&gt;</code> 构造相对灵活的条件，这样一些动态 SQL 我们就无需在 XML 中编写。</p><ul><li>更多 QueryWrapper 已经提供好的拼接方法，可以看看 <a href="https://mybatis.plus/guide/wrapper.html#abstractwrapper" target="_blank" rel="noopener">《MyBatis-Plus 文档 —— 条件构造器》</a> 。</li><li>建议 1 ：不要在 Service 中，使用 QueryWrapper 拼接动态条件。因为 BaseMapper 提供了 <code>#selectList(Wrapper queryWrapper)</code> 等方法，促使我们能够在 Service 层的逻辑中，使用 QueryWrapper 拼接动态条件，这样会导致逻辑里遍布了各种查询，使我们无法对实际有哪些查询条件做统一的管理。碰到这种情况，建议封装到对应的 Mapper 中，这样会更加简洁干净可管理。</li><li>建议 2 ：因为 QueryWrapper 暂时不支持一些类似 <code>&lt;if /&gt;</code> 等 MyBatis 的 OGNL 表达式，<a href="https://github.com/YunaiV/onemall" target="_blank" rel="noopener">onemall</a> 开源项目中，通过继承 QueryWrapper 类，封装了 <a href="https://github.com/YunaiV/onemall/blob/master/common/common-framework/src/main/java/cn/iocoder/common/framework/mybatis/QueryWrapperX.java" target="_blank" rel="noopener">QueryWrapperX</a> 类。</li></ul></li><li><p>对于 <code>#selectByIds(@Param(&quot;ids&quot;)</code> 方法，实际也可以使用 MyBatis-Plus 的 QueryWrapper 很方便的实现，这里仅仅是为了演示在 MyBatis-Plus 混合使用 XML 。</p></li><li><p>对于 <code>#selectPageByCreateTime(IPage&lt;UserDO&gt; page, @Param(&quot;createTime&quot;) Date createTime)</code>方法，是我们额外添加的，用于演示 MyBatis-Plus 提供的分页插件。</p><ul><li>更多 IPage 的内容，可以看看 <a href="https://mybatis.plus/guide/page.html" target="_blank" rel="noopener">《MyBatis-Plus 文档 —— 分页插件》</a> 。</li></ul></li></ul><p>在 <code>resources/mapper</code>路径下，创建 <code>UserMapper.xml</code> 配置文件。代码如下：</p><figure class="highlight xml"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">&lt;?xml version="1.0" encoding="UTF-8"?&gt;</span></span><br><span class="line"><span class="meta">&lt;!DOCTYPE <span class="meta-keyword">mapper</span> <span class="meta-keyword">PUBLIC</span> <span class="meta-string">"-//mybatis.org//DTD Mapper 3.0//EN"</span> <span class="meta-string">"http://mybatis.org/dtd/mybatis-3-mapper.dtd"</span>&gt;</span></span><br><span class="line"><span class="tag">&lt;<span class="name">mapper</span> <span class="attr">namespace</span>=<span class="string">"cn.javadog.labs.springboot2.mybatis.plus.mapper.UserMapper"</span>&gt;</span></span><br><span class="line"></span><br><span class="line">    <span class="tag">&lt;<span class="name">sql</span> <span class="attr">id</span>=<span class="string">"FIELDS"</span>&gt;</span></span><br><span class="line">        id, username, password, create_time</span><br><span class="line">    <span class="tag">&lt;/<span class="name">sql</span>&gt;</span></span><br><span class="line"></span><br><span class="line">    <span class="tag">&lt;<span class="name">select</span> <span class="attr">id</span>=<span class="string">"selectByIds"</span> <span class="attr">resultType</span>=<span class="string">"UserDO"</span>&gt;</span></span><br><span class="line">        SELECT</span><br><span class="line">            <span class="tag">&lt;<span class="name">include</span> <span class="attr">refid</span>=<span class="string">"FIELDS"</span> /&gt;</span></span><br><span class="line">        FROM mybatis_plus_users</span><br><span class="line">        WHERE id IN</span><br><span class="line">            <span class="tag">&lt;<span class="name">foreach</span> <span class="attr">item</span>=<span class="string">"id"</span> <span class="attr">collection</span>=<span class="string">"ids"</span> <span class="attr">separator</span>=<span class="string">","</span> <span class="attr">open</span>=<span class="string">"("</span> <span class="attr">close</span>=<span class="string">")"</span> <span class="attr">index</span>=<span class="string">""</span>&gt;</span></span><br><span class="line">                #&#123;id&#125;</span><br><span class="line">            <span class="tag">&lt;/<span class="name">foreach</span>&gt;</span></span><br><span class="line">    <span class="tag">&lt;/<span class="name">select</span>&gt;</span></span><br><span class="line"></span><br><span class="line"><span class="tag">&lt;/<span class="name">mapper</span>&gt;</span></span><br></pre></td></tr></table></figure><ul><li>是不是一下子，瘦了！</li></ul><h2 id="4-6-简单测试"><a href="#4-6-简单测试" class="headerlink" title="4.6 简单测试"></a>4.6 简单测试</h2><p>创建 <code>UserMapperTest</code> 测试类，我们来测试一下简单的 UserMapper 的每个操作。代码如下：</p><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br><span class="line">47</span><br><span class="line">48</span><br><span class="line">49</span><br><span class="line">50</span><br><span class="line">51</span><br><span class="line">52</span><br><span class="line">53</span><br><span class="line">54</span><br><span class="line">55</span><br><span class="line">56</span><br><span class="line">57</span><br><span class="line">58</span><br><span class="line">59</span><br><span class="line">60</span><br><span class="line">61</span><br><span class="line">62</span><br><span class="line">63</span><br><span class="line">64</span><br><span class="line">65</span><br><span class="line">66</span><br><span class="line">67</span><br><span class="line">68</span><br><span class="line">69</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">// UserMapperTest.java</span></span><br><span class="line"></span><br><span class="line"><span class="meta">@RunWith</span>(SpringRunner<span class="class">.<span class="keyword">class</span>)</span></span><br><span class="line"><span class="class">@<span class="title">SpringBootTest</span>(<span class="title">classes</span> </span>= MyBatisPlusApplication<span class="class">.<span class="keyword">class</span>)</span></span><br><span class="line"><span class="class"><span class="title">public</span> <span class="title">class</span> <span class="title">UserMapperTest</span> </span>&#123;</span><br><span class="line"></span><br><span class="line">    <span class="meta">@Autowired</span></span><br><span class="line">    <span class="keyword">private</span> UserMapper userMapper;</span><br><span class="line"></span><br><span class="line">    <span class="meta">@Test</span></span><br><span class="line">    <span class="function"><span class="keyword">public</span> <span class="keyword">void</span> <span class="title">testInsert</span><span class="params">()</span> </span>&#123;</span><br><span class="line">        UserDO user = <span class="keyword">new</span> UserDO().setUsername(UUID.randomUUID().toString())</span><br><span class="line">                .setPassword(<span class="string">"mybatis-plus"</span>)</span><br><span class="line">                .setCreateTime(<span class="keyword">new</span> Date())</span><br><span class="line">                <span class="comment">// 一般情况下，是否删除，可以全局枚举下。</span></span><br><span class="line">                .setDeleted(<span class="number">0</span>);</span><br><span class="line">        userMapper.insert(user);</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    <span class="meta">@Test</span></span><br><span class="line">    <span class="function"><span class="keyword">public</span> <span class="keyword">void</span> <span class="title">testUpdateById</span><span class="params">()</span> </span>&#123;</span><br><span class="line">        UserDO updateUser = <span class="keyword">new</span> UserDO().setId(<span class="number">7</span>)</span><br><span class="line">                .setPassword(<span class="string">"mybatis-plus-update"</span>);</span><br><span class="line">        userMapper.updateById(updateUser);</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    <span class="meta">@Test</span></span><br><span class="line">    <span class="function"><span class="keyword">public</span> <span class="keyword">void</span> <span class="title">testDeleteById</span><span class="params">()</span> </span>&#123;</span><br><span class="line">        userMapper.deleteById(<span class="number">7</span>);</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    <span class="meta">@Test</span></span><br><span class="line">    <span class="function"><span class="keyword">public</span> <span class="keyword">void</span> <span class="title">testSelectById</span><span class="params">()</span> </span>&#123;</span><br><span class="line">        userMapper.selectById(<span class="number">8</span>);</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    <span class="meta">@Test</span></span><br><span class="line">    <span class="function"><span class="keyword">public</span> <span class="keyword">void</span> <span class="title">testSelectByUsername</span><span class="params">()</span> </span>&#123;</span><br><span class="line">        userMapper.selectByUsername(<span class="string">"calm"</span>);</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    <span class="comment">/**</span></span><br><span class="line"><span class="comment">     * 不走逻辑删除</span></span><br><span class="line"><span class="comment">     */</span></span><br><span class="line">    <span class="meta">@Test</span></span><br><span class="line">    <span class="function"><span class="keyword">public</span> <span class="keyword">void</span> <span class="title">testSelectByIds</span><span class="params">()</span> </span>&#123;</span><br><span class="line">        List&lt;UserDO&gt; users = userMapper.selectByIds(Arrays.asList(<span class="number">7</span>, <span class="number">8</span>));</span><br><span class="line">        System.out.println(<span class="string">"users："</span> + users.size());</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    <span class="comment">/**</span></span><br><span class="line"><span class="comment">     * 走逻辑删除</span></span><br><span class="line"><span class="comment">     */</span></span><br><span class="line">    <span class="meta">@Test</span></span><br><span class="line">    <span class="function"><span class="keyword">public</span> <span class="keyword">void</span> <span class="title">testSelectByIds2</span><span class="params">()</span> </span>&#123;</span><br><span class="line">        List&lt;UserDO&gt; users = userMapper.selectByIdsWithWrapper(Arrays.asList(<span class="number">7</span>, <span class="number">8</span>));</span><br><span class="line">        System.out.println(<span class="string">"users："</span> + users.size());</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    <span class="meta">@Test</span></span><br><span class="line">    <span class="function"><span class="keyword">public</span> <span class="keyword">void</span> <span class="title">testSelectPageByCreateTime</span><span class="params">()</span> </span>&#123;</span><br><span class="line">        IPage&lt;UserDO&gt; page = <span class="keyword">new</span> Page&lt;&gt;(<span class="number">1</span>, <span class="number">10</span>);</span><br><span class="line">        <span class="comment">// 临时 Demo ，实际不建议这么写</span></span><br><span class="line">        Date createTime = <span class="keyword">new</span> Date(<span class="number">2020</span> - <span class="number">1900</span>, Calendar.JANUARY, <span class="number">8</span>);</span><br><span class="line">        page = userMapper.selectPageByCreateTime(page, createTime);</span><br><span class="line">        System.out.println(<span class="string">"users："</span> + page.getRecords().size());</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><ul><li>和 <a href="https://calm_java.gitee.io/blog/2020/01/08/labs-springboot2-mybatis/">「2.7 简单测试」</a> 差不多，只是多了一个分页的单元测试方法。</li><li>注意⚠️：通过在xml里面写的SQL是不会增加逻辑删除过滤条件的，MyBatis-Plus只对自动生成的SQL和Wrapper构建的SQL加逻辑删除过滤。</li></ul><p>总的来说，MyBatis-Plus 给我们日常开发，还是提供了蛮多便利性的，胖友不烦尝试下。</p><h1 id="5-tkmybatis"><a href="#5-tkmybatis" class="headerlink" title="5. tkmybatis"></a>5. tkmybatis</h1><p>关于 tkmybatis 的介绍，直接到 <a href="http://www.mybatis.tk/" target="_blank" rel="noopener">http://www.mybatis.tk/</a> 官网，卡姆就不多哔哔，GitHub上的文档教程其实更完整，大家可以直接看GitHub上的：<a href="https://github.com/abel533/Mapper/wiki" target="_blank" rel="noopener">MyBatis 通用 Mapper4</a>。</p><p>需要注意的是，tkmybatis 对自己的定位是 mybatis 的工具的意思，那么 tk 猜测是 toolkit 的缩写。也因此，tkmybatis 是多个开源项目组合起来的：</p><ul><li><a href="https://github.com/abel533/Mapper" target="_blank" rel="noopener">Mapper</a> ：提供通用的 MyBatis Mapper 。</li><li><a href="https://github.com/pagehelper/Mybatis-PageHelper" target="_blank" rel="noopener">Mybatis-PageHelper</a> ：提供 MyBatis 分页插件。</li></ul><blockquote><p>艿艿：说实在的，还是喜欢 MyBatis-Plus 。一站式，文档也更加齐全和易懂。</p></blockquote><h2 id="5-1-引入依赖"><a href="#5-1-引入依赖" class="headerlink" title="5.1 引入依赖"></a>5.1 引入依赖</h2><p>在 <code>pom.xml</code>文件中，引入相关依赖。</p><figure class="highlight xml"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br><span class="line">47</span><br><span class="line">48</span><br><span class="line">49</span><br><span class="line">50</span><br><span class="line">51</span><br><span class="line">52</span><br><span class="line">53</span><br><span class="line">54</span><br><span class="line">55</span><br><span class="line">56</span><br><span class="line">57</span><br><span class="line">58</span><br><span class="line">59</span><br><span class="line">60</span><br><span class="line">61</span><br><span class="line">62</span><br><span class="line">63</span><br><span class="line">64</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">&lt;?xml version="1.0" encoding="UTF-8"?&gt;</span></span><br><span class="line"><span class="tag">&lt;<span class="name">project</span> <span class="attr">xmlns</span>=<span class="string">"http://maven.apache.org/POM/4.0.0"</span></span></span><br><span class="line"><span class="tag">         <span class="attr">xmlns:xsi</span>=<span class="string">"http://www.w3.org/2001/XMLSchema-instance"</span></span></span><br><span class="line"><span class="tag">         <span class="attr">xsi:schemaLocation</span>=<span class="string">"http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"</span>&gt;</span></span><br><span class="line">        <span class="tag">&lt;<span class="name">parent</span>&gt;</span></span><br><span class="line">        <span class="tag">&lt;<span class="name">artifactId</span>&gt;</span>labs-springboot2-mybatis<span class="tag">&lt;/<span class="name">artifactId</span>&gt;</span></span><br><span class="line">        <span class="tag">&lt;<span class="name">groupId</span>&gt;</span>cn.javadog<span class="tag">&lt;/<span class="name">groupId</span>&gt;</span></span><br><span class="line">        <span class="tag">&lt;<span class="name">version</span>&gt;</span>1.0-SNAPSHOT<span class="tag">&lt;/<span class="name">version</span>&gt;</span></span><br><span class="line">    <span class="tag">&lt;/<span class="name">parent</span>&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">modelVersion</span>&gt;</span>4.0.0<span class="tag">&lt;/<span class="name">modelVersion</span>&gt;</span></span><br><span class="line"></span><br><span class="line">    <span class="tag">&lt;<span class="name">artifactId</span>&gt;</span>labs-springboot2-mybatis-tk<span class="tag">&lt;/<span class="name">artifactId</span>&gt;</span></span><br><span class="line"></span><br><span class="line">    <span class="tag">&lt;<span class="name">dependencies</span>&gt;</span></span><br><span class="line">        <span class="comment">&lt;!-- 实现对数据库连接池的自动化配置 --&gt;</span></span><br><span class="line">        <span class="tag">&lt;<span class="name">dependency</span>&gt;</span></span><br><span class="line">            <span class="tag">&lt;<span class="name">groupId</span>&gt;</span>org.springframework.boot<span class="tag">&lt;/<span class="name">groupId</span>&gt;</span></span><br><span class="line">            <span class="tag">&lt;<span class="name">artifactId</span>&gt;</span>spring-boot-starter-jdbc<span class="tag">&lt;/<span class="name">artifactId</span>&gt;</span></span><br><span class="line">        <span class="tag">&lt;/<span class="name">dependency</span>&gt;</span></span><br><span class="line">        <span class="comment">&lt;!-- 本示例，我们使用 MySQL --&gt;</span></span><br><span class="line">        <span class="tag">&lt;<span class="name">dependency</span>&gt;</span></span><br><span class="line">            <span class="tag">&lt;<span class="name">groupId</span>&gt;</span>mysql<span class="tag">&lt;/<span class="name">groupId</span>&gt;</span></span><br><span class="line">            <span class="tag">&lt;<span class="name">artifactId</span>&gt;</span>mysql-connector-java<span class="tag">&lt;/<span class="name">artifactId</span>&gt;</span></span><br><span class="line">        <span class="tag">&lt;/<span class="name">dependency</span>&gt;</span></span><br><span class="line"></span><br><span class="line">        <span class="comment">&lt;!-- 实现对 MyBatis 的自动化配置 --&gt;</span></span><br><span class="line">        <span class="tag">&lt;<span class="name">dependency</span>&gt;</span></span><br><span class="line">            <span class="tag">&lt;<span class="name">groupId</span>&gt;</span>org.mybatis.spring.boot<span class="tag">&lt;/<span class="name">groupId</span>&gt;</span></span><br><span class="line">            <span class="tag">&lt;<span class="name">artifactId</span>&gt;</span>mybatis-spring-boot-starter<span class="tag">&lt;/<span class="name">artifactId</span>&gt;</span></span><br><span class="line">        <span class="tag">&lt;/<span class="name">dependency</span>&gt;</span></span><br><span class="line"></span><br><span class="line">        <span class="comment">&lt;!-- 实现对 Mapper 的自动化配置--&gt;</span></span><br><span class="line">        <span class="tag">&lt;<span class="name">dependency</span>&gt;</span></span><br><span class="line">            <span class="tag">&lt;<span class="name">groupId</span>&gt;</span>tk.mybatis<span class="tag">&lt;/<span class="name">groupId</span>&gt;</span></span><br><span class="line">            <span class="tag">&lt;<span class="name">artifactId</span>&gt;</span>mapper-spring-boot-starter<span class="tag">&lt;/<span class="name">artifactId</span>&gt;</span></span><br><span class="line">            <span class="tag">&lt;<span class="name">version</span>&gt;</span>2.1.5<span class="tag">&lt;/<span class="name">version</span>&gt;</span></span><br><span class="line">        <span class="tag">&lt;/<span class="name">dependency</span>&gt;</span></span><br><span class="line">        <span class="comment">&lt;!-- 实现对 PageHelper 的自动化配置--&gt;</span></span><br><span class="line">        <span class="tag">&lt;<span class="name">dependency</span>&gt;</span></span><br><span class="line">            <span class="tag">&lt;<span class="name">groupId</span>&gt;</span>com.github.pagehelper<span class="tag">&lt;/<span class="name">groupId</span>&gt;</span></span><br><span class="line">            <span class="tag">&lt;<span class="name">artifactId</span>&gt;</span>pagehelper-spring-boot-starter<span class="tag">&lt;/<span class="name">artifactId</span>&gt;</span></span><br><span class="line">            <span class="tag">&lt;<span class="name">version</span>&gt;</span>1.2.5<span class="tag">&lt;/<span class="name">version</span>&gt;</span></span><br><span class="line">            <span class="tag">&lt;<span class="name">exclusions</span>&gt;</span></span><br><span class="line">                <span class="tag">&lt;<span class="name">exclusion</span>&gt;</span></span><br><span class="line">                    <span class="tag">&lt;<span class="name">groupId</span>&gt;</span>org.mybatis.spring.boot<span class="tag">&lt;/<span class="name">groupId</span>&gt;</span></span><br><span class="line">                    <span class="tag">&lt;<span class="name">artifactId</span>&gt;</span>mybatis-spring-boot-starter<span class="tag">&lt;/<span class="name">artifactId</span>&gt;</span></span><br><span class="line">                <span class="tag">&lt;/<span class="name">exclusion</span>&gt;</span></span><br><span class="line">            <span class="tag">&lt;/<span class="name">exclusions</span>&gt;</span></span><br><span class="line">        <span class="tag">&lt;/<span class="name">dependency</span>&gt;</span></span><br><span class="line"></span><br><span class="line">        <span class="comment">&lt;!-- 方便等会写单元测试 --&gt;</span></span><br><span class="line">        <span class="tag">&lt;<span class="name">dependency</span>&gt;</span></span><br><span class="line">            <span class="tag">&lt;<span class="name">groupId</span>&gt;</span>org.springframework.boot<span class="tag">&lt;/<span class="name">groupId</span>&gt;</span></span><br><span class="line">            <span class="tag">&lt;<span class="name">artifactId</span>&gt;</span>spring-boot-starter-test<span class="tag">&lt;/<span class="name">artifactId</span>&gt;</span></span><br><span class="line">            <span class="tag">&lt;<span class="name">scope</span>&gt;</span>test<span class="tag">&lt;/<span class="name">scope</span>&gt;</span></span><br><span class="line">        <span class="tag">&lt;/<span class="name">dependency</span>&gt;</span></span><br><span class="line"></span><br><span class="line">        <span class="tag">&lt;<span class="name">dependency</span>&gt;</span></span><br><span class="line">            <span class="tag">&lt;<span class="name">groupId</span>&gt;</span>org.projectlombok<span class="tag">&lt;/<span class="name">groupId</span>&gt;</span></span><br><span class="line">            <span class="tag">&lt;<span class="name">artifactId</span>&gt;</span>lombok<span class="tag">&lt;/<span class="name">artifactId</span>&gt;</span></span><br><span class="line">        <span class="tag">&lt;/<span class="name">dependency</span>&gt;</span></span><br><span class="line">    <span class="tag">&lt;/<span class="name">dependencies</span>&gt;</span></span><br><span class="line"></span><br><span class="line"><span class="tag">&lt;/<span class="name">project</span>&gt;</span></span><br></pre></td></tr></table></figure><ul><li>引入 <code>mybatis-spring-boot-starter</code> 依赖，自动化配置 MyBatis 。</li><li>引入 <code>mapper-spring-boot-starter</code> 依赖，自动化配置 Mapper 。</li><li>引入 <code>pagehelper-spring-boot-starter</code> 依赖，自动化配置 PageHelper 。</li></ul><h2 id="5-2-MyBatisTkApplication"><a href="#5-2-MyBatisTkApplication" class="headerlink" title="5.2 MyBatisTkApplication"></a>5.2 MyBatisTkApplication</h2><p>创建 <code>MyBatisTkApplication</code> 类，配置 <code>@MapperScan</code> 注解，扫描对应 Mapper 接口所在的包路径。代码如下：</p><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br></pre></td><td class="code"><pre><span class="line">&#x2F;&#x2F; MyBatisTkApplication.java</span><br><span class="line"></span><br><span class="line">@SpringBootApplication</span><br><span class="line">@MapperScan(basePackages &#x3D; &quot;cn.javadog.labs.springboot2.mybatis.tk.mapper&quot;)</span><br><span class="line">public class MyBatisTkApplication &#123;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><ul><li>注意，整列使用的是 tkmybatis 提供的 <code>tk.mybatis.spring.annotation.@MapperScan</code> 注解。</li></ul><h2 id="5-3-应用配置文件"><a href="#5-3-应用配置文件" class="headerlink" title="5.3 应用配置文件"></a>5.3 应用配置文件</h2><p>在 <code>resources</code> 目录下，创建 <code>application.yaml</code> 配置文件。配置如下：</p><figure class="highlight yaml"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br></pre></td><td class="code"><pre><span class="line"><span class="attr">spring:</span></span><br><span class="line">  <span class="comment"># datasource 数据源配置内容</span></span><br><span class="line">  <span class="attr">datasource:</span></span><br><span class="line">    <span class="attr">url:</span> <span class="string">jdbc:mysql://127.0.0.1:3306/labs-springboot2?useSSL=false&amp;useUnicode=true&amp;characterEncoding=UTF-8&amp;serverTimezone=Asia/Shanghai</span></span><br><span class="line">    <span class="attr">driver-class-name:</span> <span class="string">com.mysql.cj.jdbc.Driver</span></span><br><span class="line">    <span class="attr">username:</span> <span class="string">root</span></span><br><span class="line">    <span class="attr">password:</span> <span class="string">root</span></span><br><span class="line"></span><br><span class="line"><span class="comment"># mybatis 配置内容</span></span><br><span class="line"><span class="attr">mybatis:</span></span><br><span class="line">  <span class="attr">config-location:</span> <span class="string">classpath:mybatis-config.xml</span> <span class="comment"># 配置 MyBatis 配置文件路径</span></span><br><span class="line">  <span class="attr">mapper-locations:</span> <span class="string">classpath:mapper/*.xml</span> <span class="comment"># 配置 Mapper XML 地址</span></span><br><span class="line">  <span class="attr">type-aliases-package:</span> <span class="string">cn.javadog.labs.springboot2.mybatis.tk.dataobject</span> <span class="comment"># 配置数据库实体包路径</span></span><br><span class="line"></span><br><span class="line"><span class="comment"># mapper 配置内容</span></span><br><span class="line"><span class="attr">mapper:</span></span><br><span class="line">  <span class="attr">mappers:</span> <span class="string">cn.javadog.labs.springboot2.mybatis.tk.util.IMapper</span> <span class="comment"># 设置基础 Mapper 接口</span></span><br><span class="line">  <span class="attr">not-empty:</span> <span class="literal">true</span> <span class="comment"># 在 INSERT 和 UPDATE 操作时，是否会判断字段是否为空。即 &lt;if test='xxx != null' /&gt;</span></span><br><span class="line">  <span class="attr">identity:</span> <span class="string">MYSQL</span></span><br><span class="line"></span><br><span class="line"><span class="comment"># PageHelper 配置内容</span></span><br><span class="line"><span class="comment"># 具体的参数作用，看 https://github.com/pagehelper/Mybatis-PageHelper/blob/master/wikis/zh/HowToUse.md</span></span><br><span class="line"><span class="attr">pagehelper:</span></span><br><span class="line">  <span class="attr">helperDialect:</span> <span class="string">mysql</span> <span class="comment"># 分页插件会自动检测当前的数据库链接，自动选择合适的分页方式。 你可以配置helperDialect属性来指定分页插件使用哪种方言。</span></span><br><span class="line">  <span class="attr">reasonable:</span> <span class="literal">true</span> <span class="comment"># 分页合理化参数，默认值为false。当该参数设置为 true 时，pageNum&lt;=0 时会查询第一页， pageNum&gt;pages（超过总数时），会查询最后一页。默认false 时，直接根据参数进行查询。</span></span><br><span class="line">  <span class="attr">supportMethodsArguments:</span> <span class="literal">true</span> <span class="comment"># 支持通过 Mapper 接口参数来传递分页参数，默认值false，分页插件会从查询方法的参数值中，自动根据上面 params 配置的字段中取值，查找到合适的值时就会自动分页。 使用方法可以参考测试代码中的 com.github.pagehelper.test.basic 包下的 ArgumentsMapTest 和 ArgumentsObjTest。</span></span><br><span class="line"></span><br><span class="line"><span class="comment"># logging</span></span><br><span class="line"><span class="attr">logging:</span></span><br><span class="line">  <span class="attr">level:</span></span><br><span class="line">    <span class="comment"># dao 开启 debug 模式 mybatis 输入 sql</span></span><br><span class="line">    <span class="attr">cn.javadog:</span> <span class="string">debug</span></span><br></pre></td></tr></table></figure><ul><li>一共有 <code>mybatis</code>、<code>mapper</code>、<code>pagehelper</code> 三大块配置项。相比 MyBatis-Plus 略微复杂一些。具体每个配置项的作用，胖友看下注释。</li><li>有一点要注意，<code>cn.javadog.labs.springboot2.mybatis.tk.util.IMapper</code> 接口，需要我们自己定义，去继承 <code>tk.mybatis.mapper.common.Mapper</code> 和 <code>tk.mybatis.mapper.common.MySqlMapper</code> 接口，当然，tk还提供了其他的通用mapper，胖友可以自己根据需要继承。</li></ul><h2 id="5-4-MyBatis-配置文件"><a href="#5-4-MyBatis-配置文件" class="headerlink" title="5.4 MyBatis 配置文件"></a>5.4 MyBatis 配置文件</h2><p>在 <code>resources</code> 目录下，创建 <code>mybatis-config.xml</code> 配置文件。配置如下：</p><figure class="highlight xml"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">&lt;?xml version="1.0" encoding="UTF-8" ?&gt;</span></span><br><span class="line"><span class="meta">&lt;!DOCTYPE <span class="meta-keyword">configuration</span> <span class="meta-keyword">PUBLIC</span> <span class="meta-string">"-//mybatis.org//DTD Config 3.0//EN"</span> <span class="meta-string">"http://mybatis.org/dtd/mybatis-3-config.dtd"</span>&gt;</span></span><br><span class="line"><span class="tag">&lt;<span class="name">configuration</span>&gt;</span></span><br><span class="line"></span><br><span class="line">    <span class="tag">&lt;<span class="name">settings</span>&gt;</span></span><br><span class="line">        <span class="comment">&lt;!-- 使用驼峰命名法转换字段。 --&gt;</span></span><br><span class="line">        <span class="tag">&lt;<span class="name">setting</span> <span class="attr">name</span>=<span class="string">"mapUnderscoreToCamelCase"</span> <span class="attr">value</span>=<span class="string">"true"</span>/&gt;</span></span><br><span class="line">    <span class="tag">&lt;/<span class="name">settings</span>&gt;</span></span><br><span class="line"></span><br><span class="line">    <span class="tag">&lt;<span class="name">typeAliases</span>&gt;</span></span><br><span class="line">        <span class="tag">&lt;<span class="name">typeAlias</span> <span class="attr">alias</span>=<span class="string">"Integer"</span> <span class="attr">type</span>=<span class="string">"java.lang.Integer"</span>/&gt;</span></span><br><span class="line">        <span class="tag">&lt;<span class="name">typeAlias</span> <span class="attr">alias</span>=<span class="string">"Long"</span> <span class="attr">type</span>=<span class="string">"java.lang.Long"</span>/&gt;</span></span><br><span class="line">        <span class="tag">&lt;<span class="name">typeAlias</span> <span class="attr">alias</span>=<span class="string">"HashMap"</span> <span class="attr">type</span>=<span class="string">"java.util.HashMap"</span>/&gt;</span></span><br><span class="line">        <span class="tag">&lt;<span class="name">typeAlias</span> <span class="attr">alias</span>=<span class="string">"LinkedHashMap"</span> <span class="attr">type</span>=<span class="string">"java.util.LinkedHashMap"</span>/&gt;</span></span><br><span class="line">        <span class="tag">&lt;<span class="name">typeAlias</span> <span class="attr">alias</span>=<span class="string">"ArrayList"</span> <span class="attr">type</span>=<span class="string">"java.util.ArrayList"</span>/&gt;</span></span><br><span class="line">        <span class="tag">&lt;<span class="name">typeAlias</span> <span class="attr">alias</span>=<span class="string">"LinkedList"</span> <span class="attr">type</span>=<span class="string">"java.util.LinkedList"</span>/&gt;</span></span><br><span class="line">    <span class="tag">&lt;/<span class="name">typeAliases</span>&gt;</span></span><br><span class="line"></span><br><span class="line"><span class="tag">&lt;/<span class="name">configuration</span>&gt;</span></span><br></pre></td></tr></table></figure><ul><li>和 <a href="https://calm_java.gitee.io/blog/2020/01/08/labs-springboot2-mybatis/">「2.3 MyBatis 配置文件」</a> 一致。</li></ul><h2 id="5-5-UserDO"><a href="#5-5-UserDO" class="headerlink" title="5.5 UserDO"></a>5.5 UserDO</h2><p>创建 <code>UserDO</code> 类，用户 DO 。代码如下：</p><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">// UserDO.java</span></span><br><span class="line"></span><br><span class="line"><span class="meta">@Data</span></span><br><span class="line"><span class="meta">@Accessors</span>(chain = <span class="keyword">true</span>)</span><br><span class="line"><span class="meta">@Table</span>(name = <span class="string">"mybatis_tk_users"</span>)</span><br><span class="line"><span class="keyword">public</span> <span class="class"><span class="keyword">class</span> <span class="title">UserDO</span> </span>&#123;</span><br><span class="line"></span><br><span class="line">    <span class="comment">/**</span></span><br><span class="line"><span class="comment">     * 用户编号</span></span><br><span class="line"><span class="comment">     * <span class="doctag">@Id</span> 表示该字段为主键 ID</span></span><br><span class="line"><span class="comment">     * <span class="doctag">@GeneratedValue</span> strategy 设置使用数据库主键自增策略；generator 设置插入完成后，查询最后生成的 ID 填充到该属性中。</span></span><br><span class="line"><span class="comment">     */</span></span><br><span class="line">    <span class="meta">@Id</span></span><br><span class="line">    <span class="meta">@GeneratedValue</span>(strategy = GenerationType.IDENTITY, generator = <span class="string">"JDBC"</span>)</span><br><span class="line">    <span class="keyword">private</span> Integer id;</span><br><span class="line"></span><br><span class="line">    <span class="comment">/**</span></span><br><span class="line"><span class="comment">     * 账号</span></span><br><span class="line"><span class="comment">     */</span></span><br><span class="line">    <span class="keyword">private</span> String username;</span><br><span class="line"></span><br><span class="line">    <span class="comment">/**</span></span><br><span class="line"><span class="comment">     * 密码（明文）</span></span><br><span class="line"><span class="comment">     *</span></span><br><span class="line"><span class="comment">     * ps：生产环境下，千万不要明文噢</span></span><br><span class="line"><span class="comment">     */</span></span><br><span class="line">    <span class="keyword">private</span> String password;</span><br><span class="line"></span><br><span class="line">    <span class="comment">/**</span></span><br><span class="line"><span class="comment">     * 创建时间</span></span><br><span class="line"><span class="comment">     */</span></span><br><span class="line">    <span class="keyword">private</span> Date createTime;</span><br><span class="line"></span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><ul><li>因为 Mapper 暂时不支持逻辑删除功能，所以这里我们去除了 <code>deleted</code> 属性。Mapper 的开发者，倾向使用者，自己在业务逻辑中实现逻辑删除。</li><li><code>@Table</code>、<code>@Id</code>、<code>@GeneratedValue</code> 注解，使用的是 JPA 提供的注解。如果不知道怎么引入这三个注解，胖友可以看看 <code>UserDO.java</code> 类。</li></ul><p>对应的创建表的 SQL 如下：</p><figure class="highlight sql"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">CREATE</span> <span class="keyword">TABLE</span> <span class="string">`mybatis_tk_users`</span> (</span><br><span class="line">  <span class="string">`id`</span> <span class="built_in">int</span>(<span class="number">11</span>) <span class="keyword">NOT</span> <span class="literal">NULL</span> AUTO_INCREMENT <span class="keyword">COMMENT</span> <span class="string">'用户编号'</span>,</span><br><span class="line">  <span class="string">`username`</span> <span class="built_in">varchar</span>(<span class="number">64</span>) <span class="keyword">COLLATE</span> utf8mb4_bin <span class="keyword">DEFAULT</span> <span class="literal">NULL</span> <span class="keyword">COMMENT</span> <span class="string">'账号'</span>,</span><br><span class="line">  <span class="string">`password`</span> <span class="built_in">varchar</span>(<span class="number">32</span>) <span class="keyword">COLLATE</span> utf8mb4_bin <span class="keyword">DEFAULT</span> <span class="literal">NULL</span> <span class="keyword">COMMENT</span> <span class="string">'密码'</span>,</span><br><span class="line">  <span class="string">`create_time`</span> datetime <span class="keyword">DEFAULT</span> <span class="literal">NULL</span> <span class="keyword">COMMENT</span> <span class="string">'创建时间'</span>,</span><br><span class="line">  PRIMARY <span class="keyword">KEY</span> (<span class="string">`id`</span>),</span><br><span class="line">  <span class="keyword">UNIQUE</span> <span class="keyword">KEY</span> <span class="string">`idx_username`</span> (<span class="string">`username`</span>)</span><br><span class="line">) <span class="keyword">ENGINE</span>=<span class="keyword">InnoDB</span> <span class="keyword">DEFAULT</span> <span class="keyword">CHARSET</span>=utf8mb4 <span class="keyword">COLLATE</span>=utf8mb4_bin;</span><br></pre></td></tr></table></figure><h2 id="5-6-UserMapper"><a href="#5-6-UserMapper" class="headerlink" title="5.6 UserMapper"></a>5.6 UserMapper</h2><p>创建 <code>UserMapper</code> 接口。代码如下：</p><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">// UserMapper.java</span></span><br><span class="line"></span><br><span class="line"><span class="meta">@Repository</span></span><br><span class="line"><span class="keyword">public</span> <span class="class"><span class="keyword">interface</span> <span class="title">UserMapper</span> <span class="keyword">extends</span> <span class="title">IMapper</span>&lt;<span class="title">UserDO</span>&gt; </span>&#123;</span><br><span class="line"></span><br><span class="line">    <span class="function"><span class="keyword">default</span> UserDO <span class="title">selectByUsername</span><span class="params">(@Param(<span class="string">"username"</span>)</span> String username) </span>&#123;</span><br><span class="line">        Example example = <span class="keyword">new</span> Example(UserDO<span class="class">.<span class="keyword">class</span>)</span>;</span><br><span class="line">        <span class="comment">// 创建 Criteria 对象，设置 username 查询条件</span></span><br><span class="line">        example.createCriteria().andEqualTo(<span class="string">"username"</span>, username);</span><br><span class="line">        <span class="comment">// 执行查询</span></span><br><span class="line">        <span class="keyword">return</span> selectOneByExample(example);</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    <span class="function">List&lt;UserDO&gt; <span class="title">selectByIds</span><span class="params">(@Param(<span class="string">"ids"</span>)</span> Collection&lt;Integer&gt; ids)</span>;</span><br><span class="line"></span><br><span class="line">    <span class="function"><span class="keyword">default</span> List&lt;UserDO&gt; <span class="title">selectListByCreateTime</span><span class="params">(@Param(<span class="string">"createTime"</span>)</span> Date createTime) </span>&#123;</span><br><span class="line">        Example example = <span class="keyword">new</span> Example(UserDO<span class="class">.<span class="keyword">class</span>)</span>;</span><br><span class="line">        <span class="comment">// 创建 Criteria 对象，设置 create_time 查询条件</span></span><br><span class="line">        example.createCriteria().andGreaterThan(<span class="string">"createTime"</span>, createTime);</span><br><span class="line">        <span class="keyword">return</span> selectByExample(example);</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><ul><li>继承的接口，是我们自己定义的 <code>IMapper</code> 接口。</li><li>在 MyBatis-Plus 中，我们使用 QueryWrapper 拼装动态 SQL 。而在 tkmybatis 中，通过使用它提供的 Example 和 Criteria 类。</li><li>关于分页，PageHelper 的使用方式，有点神奇，我们在 <a href="https://calm_java.gitee.io/blog/2020/01/08/labs-springboot2-mybatis/">「5.6 简单测试」</a> 来看。</li></ul><p>在 <code>resources/mapper</code> 路径下，创建 <code>UserMapper.xml</code> 配置文件。代码如下：</p><figure class="highlight xml"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">&lt;?xml version="1.0" encoding="UTF-8"?&gt;</span></span><br><span class="line"><span class="meta">&lt;!DOCTYPE <span class="meta-keyword">mapper</span> <span class="meta-keyword">PUBLIC</span> <span class="meta-string">"-//mybatis.org//DTD Mapper 3.0//EN"</span> <span class="meta-string">"http://mybatis.org/dtd/mybatis-3-mapper.dtd"</span>&gt;</span></span><br><span class="line"><span class="tag">&lt;<span class="name">mapper</span> <span class="attr">namespace</span>=<span class="string">"cn.javadog.labs.springboot2.mybatis.tk.mapper.UserMapper"</span>&gt;</span></span><br><span class="line"></span><br><span class="line">    <span class="tag">&lt;<span class="name">sql</span> <span class="attr">id</span>=<span class="string">"FIELDS"</span>&gt;</span></span><br><span class="line">        id, username, password, create_time</span><br><span class="line">    <span class="tag">&lt;/<span class="name">sql</span>&gt;</span></span><br><span class="line"></span><br><span class="line">    <span class="tag">&lt;<span class="name">select</span> <span class="attr">id</span>=<span class="string">"selectByIds"</span> <span class="attr">resultType</span>=<span class="string">"UserDO"</span>&gt;</span></span><br><span class="line">        SELECT</span><br><span class="line">            <span class="tag">&lt;<span class="name">include</span> <span class="attr">refid</span>=<span class="string">"FIELDS"</span> /&gt;</span></span><br><span class="line">        FROM mybatis_tk_users</span><br><span class="line">        WHERE id IN</span><br><span class="line">            <span class="tag">&lt;<span class="name">foreach</span> <span class="attr">item</span>=<span class="string">"id"</span> <span class="attr">collection</span>=<span class="string">"ids"</span> <span class="attr">separator</span>=<span class="string">","</span> <span class="attr">open</span>=<span class="string">"("</span> <span class="attr">close</span>=<span class="string">")"</span> <span class="attr">index</span>=<span class="string">""</span>&gt;</span></span><br><span class="line">                #&#123;id&#125;</span><br><span class="line">            <span class="tag">&lt;/<span class="name">foreach</span>&gt;</span></span><br><span class="line">    <span class="tag">&lt;/<span class="name">select</span>&gt;</span></span><br><span class="line"></span><br><span class="line"><span class="tag">&lt;/<span class="name">mapper</span>&gt;</span></span><br></pre></td></tr></table></figure><ul><li>这个没有差别哈。</li></ul><h2 id="5-7-简单测试"><a href="#5-7-简单测试" class="headerlink" title="5.7 简单测试"></a>5.7 简单测试</h2><p>创建 <code>UserMapperTest</code> 测试类，我们来测试一下简单的 UserMapper 的每个操作。代码如下：</p><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br><span class="line">47</span><br><span class="line">48</span><br><span class="line">49</span><br><span class="line">50</span><br><span class="line">51</span><br><span class="line">52</span><br><span class="line">53</span><br><span class="line">54</span><br><span class="line">55</span><br><span class="line">56</span><br><span class="line">57</span><br><span class="line">58</span><br><span class="line">59</span><br><span class="line">60</span><br><span class="line">61</span><br><span class="line">62</span><br><span class="line">63</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">// UserMapperTest.java</span></span><br><span class="line"></span><br><span class="line"><span class="meta">@RunWith</span>(SpringRunner<span class="class">.<span class="keyword">class</span>)</span></span><br><span class="line"><span class="class">@<span class="title">SpringBootTest</span>(<span class="title">classes</span> </span>= MyBatisTkApplication<span class="class">.<span class="keyword">class</span>)</span></span><br><span class="line"><span class="class"><span class="title">public</span> <span class="title">class</span> <span class="title">UserMapperTest</span> </span>&#123;</span><br><span class="line"></span><br><span class="line">    <span class="meta">@Autowired</span></span><br><span class="line">    <span class="keyword">private</span> UserMapper userMapper;</span><br><span class="line"></span><br><span class="line">    <span class="meta">@Test</span></span><br><span class="line">    <span class="function"><span class="keyword">public</span> <span class="keyword">void</span> <span class="title">testInsert</span><span class="params">()</span> </span>&#123;</span><br><span class="line">        UserDO user = <span class="keyword">new</span> UserDO().setUsername(UUID.randomUUID().toString())</span><br><span class="line">                .setPassword(<span class="string">"mybatis_tk_insert"</span>).setCreateTime(<span class="keyword">new</span> Date());</span><br><span class="line">        userMapper.insert(user);</span><br><span class="line">        System.out.println(user.getId());</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    <span class="meta">@Test</span></span><br><span class="line">    <span class="function"><span class="keyword">public</span> <span class="keyword">void</span> <span class="title">testUpdateById</span><span class="params">()</span> </span>&#123;</span><br><span class="line">        UserDO updateUser = <span class="keyword">new</span> UserDO().setId(<span class="number">1</span>).setUsername(<span class="string">"calm"</span>)</span><br><span class="line">                .setPassword(<span class="string">"mybatis_tk_update"</span>);</span><br><span class="line">        userMapper.updateByPrimaryKeySelective(updateUser);</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    <span class="meta">@Test</span></span><br><span class="line">    <span class="function"><span class="keyword">public</span> <span class="keyword">void</span> <span class="title">testDeleteById</span><span class="params">()</span> </span>&#123;</span><br><span class="line">        userMapper.deleteByPrimaryKey(<span class="number">2</span>);</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    <span class="meta">@Test</span></span><br><span class="line">    <span class="function"><span class="keyword">public</span> <span class="keyword">void</span> <span class="title">testSelectById</span><span class="params">()</span> </span>&#123;</span><br><span class="line">        userMapper.selectByPrimaryKey(<span class="number">1</span>);</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    <span class="meta">@Test</span></span><br><span class="line">    <span class="function"><span class="keyword">public</span> <span class="keyword">void</span> <span class="title">testSelectByUsername</span><span class="params">()</span> </span>&#123;</span><br><span class="line">        userMapper.selectByUsername(<span class="string">"calm"</span>);</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    <span class="meta">@Test</span></span><br><span class="line">    <span class="function"><span class="keyword">public</span> <span class="keyword">void</span> <span class="title">testSelectByIds</span><span class="params">()</span> </span>&#123;</span><br><span class="line">        List&lt;UserDO&gt; users = userMapper.selectByIds(Arrays.asList(<span class="number">1</span>, <span class="number">3</span>));</span><br><span class="line">        System.out.println(<span class="string">"users："</span> + users.size());</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    <span class="comment">/**</span></span><br><span class="line"><span class="comment">     * 更多使用，可以参考 https://github.com/pagehelper/Mybatis-PageHelper/blob/master/wikis/zh/HowToUse.md</span></span><br><span class="line"><span class="comment">     */</span></span><br><span class="line">    <span class="meta">@Test</span></span><br><span class="line">    <span class="function"><span class="keyword">public</span> <span class="keyword">void</span> <span class="title">testSelectPageByCreateTime</span><span class="params">()</span> </span>&#123;</span><br><span class="line">        <span class="comment">// 设置分页</span></span><br><span class="line">        PageHelper.startPage(<span class="number">1</span>, <span class="number">10</span>);</span><br><span class="line">        <span class="comment">// 临时 Demo ，实际不建议这么写</span></span><br><span class="line">        Date createTime = <span class="keyword">new</span> Date(<span class="number">2018</span> - <span class="number">1900</span>, Calendar.JANUARY, <span class="number">8</span>);</span><br><span class="line">        <span class="comment">// 执行列表查询</span></span><br><span class="line">        <span class="comment">// PageHelper 会自动发起分页的数量查询，设置到 PageHelper 中，实际返回的是 com.github.pagehelper.Page 代理对象 ， 它继承自 List</span></span><br><span class="line">        List&lt;UserDO&gt; users = userMapper.selectListByCreateTime(createTime);</span><br><span class="line">        <span class="comment">// 转换成 PageInfo 对象，并输出分页</span></span><br><span class="line">        PageInfo&lt;UserDO&gt; page = <span class="keyword">new</span> PageInfo&lt;&gt;(users);</span><br><span class="line">        System.out.println(page.getTotal());</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><ul><li>分页逻辑，在 <code>#testSelectPageByCreateTime()</code> 方法中，我们已经进行实现。相比来说，个人不是很喜欢 PageHelper 这种方式。也和朋友聊了下，他们也倾向类似 MyBatis-Plus 提供的分页方式。</li></ul><h2 id="5-8-自定义扩展"><a href="#5-8-自定义扩展" class="headerlink" title="5.8 自定义扩展"></a>5.8 自定义扩展</h2><h3 id="5-8-1-自定义逻辑删除通用mapper"><a href="#5-8-1-自定义逻辑删除通用mapper" class="headerlink" title="5.8.1  自定义逻辑删除通用mapper"></a>5.8.1 自定义逻辑删除通用mapper</h3><p>由于tkmapper本身不支持逻辑删除，而项目必然是需要的，我们不希望每个mapper都写一套逻辑删除的代码，而希望像常见的CURD一样，由框架替我们完成，可以采用下面的方式：</p><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">//LogicDeleteMapper.java</span></span><br><span class="line"><span class="meta">@RegisterMapper</span></span><br><span class="line"><span class="keyword">public</span> <span class="class"><span class="keyword">interface</span> <span class="title">LogicDeleteMapper</span>&lt;<span class="title">T</span>&gt;  </span>&#123;</span><br><span class="line"></span><br><span class="line">  	<span class="comment">// &lt;1&gt;</span></span><br><span class="line">    <span class="meta">@Delete</span>(<span class="string">"UPDATE $&#123;tableName&#125; SET is_archive=1 WHERE id=#&#123;id&#125;"</span>)</span><br><span class="line">    <span class="function"><span class="keyword">int</span> <span class="title">logicDeleteById</span><span class="params">(@Param(<span class="string">"tableName"</span>)</span> String tableName, @<span class="title">Param</span><span class="params">(<span class="string">"id"</span>)</span> String id)</span>;</span><br><span class="line"></span><br><span class="line">  	<span class="comment">// &lt;2&gt;</span></span><br><span class="line">    <span class="meta">@UpdateProvider</span>(type = LogicDeleteProvider<span class="class">.<span class="keyword">class</span>, <span class="title">method</span> </span>= <span class="string">"dynamicSQL"</span>)</span><br><span class="line">    <span class="function"><span class="keyword">int</span> <span class="title">logicDeleteByExample</span><span class="params">(Object example)</span></span>;</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="comment">/**----------------------------*/</span></span><br><span class="line"></span><br><span class="line"><span class="comment">// LogicDeleteProvider.java</span></span><br><span class="line"><span class="keyword">public</span> <span class="class"><span class="keyword">class</span> <span class="title">LogicDeleteProvider</span> <span class="keyword">extends</span> <span class="title">MapperTemplate</span> </span>&#123;</span><br><span class="line"></span><br><span class="line">    <span class="function"><span class="keyword">public</span> <span class="title">LogicDeleteProvider</span><span class="params">(Class&lt;?&gt; mapperClass, MapperHelper mapperHelper)</span> </span>&#123;</span><br><span class="line">        <span class="keyword">super</span>(mapperClass, mapperHelper);</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    <span class="comment">/**</span></span><br><span class="line"><span class="comment">     * 逻辑删除</span></span><br><span class="line"><span class="comment">     */</span></span><br><span class="line">    <span class="function"><span class="keyword">public</span> String <span class="title">logicDeleteByExample</span><span class="params">(MappedStatement ms)</span> </span>&#123;</span><br><span class="line">        Class&lt;?&gt; entityClass = getEntityClass(ms);</span><br><span class="line">        StringBuilder sql = <span class="keyword">new</span> StringBuilder();</span><br><span class="line">        <span class="keyword">if</span> (isCheckExampleEntityClass()) &#123;</span><br><span class="line">            sql.append(SqlHelper.exampleCheck(entityClass));</span><br><span class="line">        &#125;</span><br><span class="line">        <span class="comment">//如果设置了安全删除，就不允许执行不带查询条件的 delete 方法</span></span><br><span class="line">        <span class="keyword">if</span> (getConfig().isSafeDelete()) &#123;</span><br><span class="line">            sql.append(SqlHelper.exampleHasAtLeastOneCriteriaCheck(<span class="string">"_parameter"</span>));</span><br><span class="line">        &#125;</span><br><span class="line">        sql.append(SqlHelper.updateTable(entityClass, tableName(entityClass)));</span><br><span class="line">        sql.append(<span class="string">" SET delete=1 "</span>);</span><br><span class="line">        sql.append(SqlHelper.exampleWhereClause());</span><br><span class="line">        <span class="keyword">return</span> sql.toString();</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><ul><li>&lt;1&gt; 和普通加在注解上的SQL一样，要求调用者声明表名和主键<ul><li>注意表名使用 <code>${}</code>，而不是<code>#{}</code>，因为后者为了防止SQL注入，会在字符串两边加上引号，生成的SQL无法执行，也说明这个方式实际并不可靠，有SQL注入的风险</li></ul></li><li>&lt;2&gt; 通过自定义 <code>Provider</code> 的方式，相比方法一要强大的多，借助tk强大的<code>mapperHelper</code> 工具拼接SQL，不过依然有一些硬编码，如<code>SET delete=1</code>，就看胖友如何取舍了</li><li>记得加上<code>@RegisterMapper</code>，这样就会被tk识别为通用mapper，需要的地方，继承即可。且不能放在<code>@MapperScan</code>扫描的包，因为它有范型。</li></ul><h1 id="666-彩蛋"><a href="#666-彩蛋" class="headerlink" title="666. 彩蛋"></a>666. 彩蛋</h1><p>总的来说，个人还是比较推荐在项目中使用 MyBatis-Plus 。也问了好些朋友，目前都处于要么在使用 MyBatis-Plus ，要么新项目考虑使用 MyBatis-Plus 。</p><p>在之前使用 Spring Data JPA 的过程中，还是比较喜欢可以通过方法名，自动生成对应的 CRUD 操作。所以，就琢磨有没可能 Spring Data JPA 底层实现，除了使用 Hibernate ，是否有可能使用 MyBatis 呢？于是乎，在 Github 上竟然搜到了 <a href="https://github.com/lkqm/spring-data-jpa-mybatis" target="_blank" rel="noopener">spring-data-jpa-mybatis</a> 项目。有点神奇，感兴趣的胖友可以试试。当然，生产上不是很建议哈。</p><p>推荐阅读：</p><ul><li><a href="http://www.iocoder.cn/Performance-Testing/MySQL-benchmark/?self" target="_blank" rel="noopener">《性能测试 —— MySQL 基准测试》</a></li><li><a href="http://www.iocoder.cn/Spring-Boot/dynamic-datasource/?self" target="_blank" rel="noopener">《芋道 Spring Boot 多数据源（读写分离）入门》</a> 对应 <a href="https://github.com/YunaiV/SpringBoot-Labs/tree/master/lab-17" target="_blank" rel="noopener">lab-17</a> 。</li><li><a href="http://www.iocoder.cn/Spring-Boot/sharding-datasource/?self" target="_blank" rel="noopener">《芋道 Spring Boot 分库分表入门》</a> 对应 <a href="https://github.com/YunaiV/SpringBoot-Labs/tree/master/lab-18" target="_blank" rel="noopener">lab-18</a> 。</li></ul></div><div class="article-footer"><blockquote class="mt-2x"><ul class="post-copyright list-unstyled"><li class="post-copyright-link hidden-xs"><strong>本文链接：</strong> <a href="https://calm_java.gitee.io/blog/2020/01/08/labs-springboot2-mybatis/" title="Spring Boot MyBatis 入门" target="_blank" rel="external">https://calm_java.gitee.io/blog/2020/01/08/labs-springboot2-mybatis/</a></li><li class="post-copyright-license"><strong>版权声明： </strong>本博客所有文章除特别声明外，均采用 <a href="http://creativecommons.org/licenses/by/4.0/deed.zh" target="_blank" rel="external">CC BY 4.0 CN协议</a> 许可协议。转载请注明出处！</li></ul></blockquote><div class="panel panel-default panel-badger"><div class="panel-body"><figure class="media"><div class="media-left"><a href="https://github.com/yuyong725" target="_blank" class="img-burn thumb-sm visible-lg"><img src="/blog/images/avatar.jpg" class="img-rounded w-full" alt=""></a></div><div class="media-body"><h3 class="media-heading"><a href="https://github.com/yuyong725" target="_blank"><span class="text-dark">卡姆</span><small class="ml-1x">a Java coder need calm</small></a></h3><div>享受编程</div></div></figure></div></div></div></article><section id="comments"></section></div><nav class="bar bar-footer clearfix" data-stick-bottom><div class="bar-inner"><ul class="pager pull-left"><li class="prev"><a href="/blog/2020/01/08/labs-springboot2-jpa/" title="Spring Boot JPA 入门"><i class="icon icon-angle-left" aria-hidden="true"></i><span>&nbsp;&nbsp;上一篇</span></a></li><li class="next"><a href="/blog/2020/01/07/labs-springboot2-datasource-pool/" title="Spring Boot 数据库连接池入门"><span>下一篇&nbsp;&nbsp;</span><i class="icon icon-angle-right" aria-hidden="true"></i></a></li><li class="toggle-toc"><a class="toggle-btn" data-toggle="collapse" href="#collapseToc" aria-expanded="true" title="文章目录" role="button"><span>[&nbsp;</span><span>文章目录</span> <i class="text-collapsed icon icon-anchor"></i> <i class="text-in icon icon-close"></i> <span>]</span></a></li></ul><button type="button" class="btn btn-fancy btn-donate pop-onhover bg-gradient-warning" data-toggle="modal" data-target="#donateModal"><span>赏</span></button><div class="bar-right"><div class="share-component" data-sites="wechat" data-mobile-sites="wechat"></div></div></div></nav><div class="modal modal-center modal-small modal-xs-full fade" id="donateModal" tabindex="-1" role="dialog"><div class="modal-dialog" role="document"><div class="modal-content donate"><button type="button" class="close" data-dismiss="modal" aria-label="Close"><span aria-hidden="true">&times;</span></button><div class="modal-body"><div class="donate-box"><div class="donate-head"><p>感谢您的支持，我会继续努力的!</p></div><div class="tab-content"><div role="tabpanel" class="tab-pane fade active in" id="alipay"><div class="donate-payimg"><img src="/blog/images/donate/alipayimg.jpeg" alt="扫码支持" title="扫一扫"></div><p class="text-muted mv">扫码打赏，你说多少就多少</p><p class="text-grey">打开支付宝扫一扫，即可进行扫码打赏哦</p></div><div role="tabpanel" class="tab-pane fade" id="wechatpay"><div class="donate-payimg"><img src="/blog/images/donate/wechatpayimg.jpeg" alt="扫码支持" title="扫一扫"></div><p class="text-muted mv">扫码打赏，你说多少就多少</p><p class="text-grey">打开微信扫一扫，即可进行扫码打赏哦</p></div></div><div class="donate-footer"><ul class="nav nav-tabs nav-justified" role="tablist"><li role="presentation" class="active"><a href="#alipay" id="alipay-tab" role="tab" data-toggle="tab" aria-controls="alipay" aria-expanded="true"><i class="icon icon-alipay"></i> 支付宝</a></li><li role="presentation"><a href="#wechatpay" role="tab" id="wechatpay-tab" data-toggle="tab" aria-controls="wechatpay" aria-expanded="false"><i class="icon icon-wepay"></i> 微信支付</a></li></ul></div></div></div></div></div></div></main><footer class="footer" itemscope itemtype="http://schema.org/WPFooter"></footer><script src="//cdn.jsdelivr.net/npm/jquery@1.12.4/dist/jquery.min.js"></script><script>window.jQuery||document.write('<script src="js/jquery.min.js"><\/script>')</script><script src="/blog/js/plugin.min.js"></script><script src="/blog/js/application.js"></script><script>!function(T){var N={TRANSLATION:{POSTS:"文章",PAGES:"页面",CATEGORIES:"分类",TAGS:"标签",UNTITLED:"(未命名)"},ROOT_URL:"/blog/",CONTENT_URL:"/blog/content.json"};T.INSIGHT_CONFIG=N}(window)</script><script src="/blog/js/insight.js"></script><script async src="//busuanzi.ibruce.info/busuanzi/2.3/busuanzi.pure.mini.js"></script><script src="//cdn.jsdelivr.net/npm/gitalk@1.4.0/dist/gitalk.min.js"></script><script src="//cdn.jsdelivr.net/npm/blueimp-md5@2.10.0/js/md5.min.js"></script><script type="text/javascript">var gitalk=new Gitalk({clientID:"adf0c8bfdd8796029917",clientSecret:"a88c2e2e83e2b180f62ad927dcb347871dfe9f4b",repo:"myblog-comment",owner:"yuyong725",admin:["yuyong725"],id:md5(location.pathname),distractionFreeMode:!0});gitalk.render("comments")</script></body></html><!-- rebuild by neat -->